From 501aa9463591572d349843b3dbd44b4e378b5856 Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Fri, 29 Mar 2024 16:08:57 +0300 Subject: [PATCH] import pam-1.3.1-33.el8 --- .gitignore | 2 + .pam.metadata | 2 + SOURCES/Linux-PAM-1.3.1.tar.xz.asc | 7 + SOURCES/config-util.5 | 36 + SOURCES/config-util.pamd | 8 + SOURCES/dlopen.sh | 75 + SOURCES/fingerprint-auth.pamd | 19 + SOURCES/gpl-2.0.txt | 339 +++ SOURCES/other.pamd | 5 + SOURCES/pam-1.1.0-console-nochmod.patch | 26 + SOURCES/pam-1.1.0-notally.patch | 12 + SOURCES/pam-1.1.1-console-errmsg.patch | 12 + SOURCES/pam-1.1.3-nouserenv.patch | 27 + SOURCES/pam-1.1.6-limits-user.patch | 20 + SOURCES/pam-1.1.8-audit-user-mgmt.patch | 31 + SOURCES/pam-1.1.8-full-relro.patch | 88 + SOURCES/pam-1.2.0-redhat-modules.patch | 23 + SOURCES/pam-1.2.0-unix-no-fallback.patch | 73 + SOURCES/pam-1.2.1-console-devname.patch | 9 + SOURCES/pam-1.2.1-faillock-admin-group.patch | 133 + SOURCES/pam-1.2.1-faillock.patch | 1759 +++++++++++++ SOURCES/pam-1.3.0-pwhistory-helper.patch | 806 ++++++ SOURCES/pam-1.3.0-unix-nomsg.patch | 16 + .../pam-1.3.1-access-handle-hostnames.patch | 158 ++ SOURCES/pam-1.3.1-audit-error.patch | 35 + SOURCES/pam-1.3.1-authtok-verify-fix.patch | 88 + SOURCES/pam-1.3.1-console-build.patch | 11 + SOURCES/pam-1.3.1-coverity.patch | 185 ++ .../pam-1.3.1-faillock-create-tallydir.patch | 13 + ...m-1.3.1-faillock-load-conf-from-file.patch | 1212 +++++++++ SOURCES/pam-1.3.1-faillock-update.patch | 1186 +++++++++ SOURCES/pam-1.3.1-fds-closing.patch | 70 + SOURCES/pam-1.3.1-inline.patch | 105 + SOURCES/pam-1.3.1-lastlog-no-showfailed.patch | 82 + .../pam-1.3.1-lastlog-unlimited-fsize.patch | 227 ++ SOURCES/pam-1.3.1-motd-manpage.patch | 25 + SOURCES/pam-1.3.1-namespace-gdm-doc.patch | 68 + SOURCES/pam-1.3.1-namespace-mntopts.patch | 131 + SOURCES/pam-1.3.1-namespace-protect-dir.patch | 58 + SOURCES/pam-1.3.1-noflex.patch | 24 + SOURCES/pam-1.3.1-pam-cc-compat.patch | 63 + .../pam-1.3.1-pam-keyinit-thread-safe.patch | 125 + ...pam-1.3.1-pam-limits-unlimited-value.patch | 78 + SOURCES/pam-1.3.1-pam-misc-configurable.patch | 29 + .../pam-1.3.1-pam-modutil-close-write.patch | 74 + ...1-pam-motd-avoid-unnecessary-logging.patch | 283 ++ .../pam-1.3.1-pam-motd-fix-memory-leak.patch | 57 + ....3.1-pam-motd-fix-segmentation-fault.patch | 133 + ...pam-motd-support-multiple-motd-paths.patch | 691 +++++ ....1-pam-pwhistory-load-conf-from-file.patch | 573 ++++ ...b-prevent-garbage-characters-from-db.patch | 111 + .../pam-1.3.1-pam-usertype-SYS_UID_MAX.patch | 75 + SOURCES/pam-1.3.1-pam-usertype.patch | 712 +++++ SOURCES/pam-1.3.1-tty-audit-manfix.patch | 33 + SOURCES/pam-1.3.1-unix-default-rounds.patch | 12 + SOURCES/pam-1.3.1-unix-enable-bcrypt.patch | 174 ++ SOURCES/pam-1.3.1-unix-improve-logging.patch | 57 + .../pam-1.3.1-wheel-pam_ruser-fallback.patch | 134 + ...pam-faillock-avoid-logging-erroneous.patch | 37 + ....1-pam-faillock-clarify-missing-user.patch | 53 + ...stlog-check-localtime_r-return-value.patch | 41 + SOURCES/pamtmp.conf | 4 + SOURCES/password-auth.pamd | 18 + SOURCES/postlogin.5 | 46 + SOURCES/postlogin.pamd | 8 + SOURCES/smartcard-auth.pamd | 4 + SOURCES/system-auth.5 | 58 + SOURCES/system-auth.pamd | 18 + SPECS/pam.spec | 2324 +++++++++++++++++ 69 files changed, 13231 insertions(+) create mode 100644 .gitignore create mode 100644 .pam.metadata create mode 100644 SOURCES/Linux-PAM-1.3.1.tar.xz.asc create mode 100644 SOURCES/config-util.5 create mode 100644 SOURCES/config-util.pamd create mode 100755 SOURCES/dlopen.sh create mode 100644 SOURCES/fingerprint-auth.pamd create mode 100644 SOURCES/gpl-2.0.txt create mode 100644 SOURCES/other.pamd create mode 100644 SOURCES/pam-1.1.0-console-nochmod.patch create mode 100644 SOURCES/pam-1.1.0-notally.patch create mode 100644 SOURCES/pam-1.1.1-console-errmsg.patch create mode 100644 SOURCES/pam-1.1.3-nouserenv.patch create mode 100644 SOURCES/pam-1.1.6-limits-user.patch create mode 100644 SOURCES/pam-1.1.8-audit-user-mgmt.patch create mode 100644 SOURCES/pam-1.1.8-full-relro.patch create mode 100644 SOURCES/pam-1.2.0-redhat-modules.patch create mode 100644 SOURCES/pam-1.2.0-unix-no-fallback.patch create mode 100644 SOURCES/pam-1.2.1-console-devname.patch create mode 100644 SOURCES/pam-1.2.1-faillock-admin-group.patch create mode 100644 SOURCES/pam-1.2.1-faillock.patch create mode 100644 SOURCES/pam-1.3.0-pwhistory-helper.patch create mode 100644 SOURCES/pam-1.3.0-unix-nomsg.patch create mode 100644 SOURCES/pam-1.3.1-access-handle-hostnames.patch create mode 100644 SOURCES/pam-1.3.1-audit-error.patch create mode 100644 SOURCES/pam-1.3.1-authtok-verify-fix.patch create mode 100644 SOURCES/pam-1.3.1-console-build.patch create mode 100644 SOURCES/pam-1.3.1-coverity.patch create mode 100644 SOURCES/pam-1.3.1-faillock-create-tallydir.patch create mode 100644 SOURCES/pam-1.3.1-faillock-load-conf-from-file.patch create mode 100644 SOURCES/pam-1.3.1-faillock-update.patch create mode 100644 SOURCES/pam-1.3.1-fds-closing.patch create mode 100644 SOURCES/pam-1.3.1-inline.patch create mode 100644 SOURCES/pam-1.3.1-lastlog-no-showfailed.patch create mode 100644 SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch create mode 100644 SOURCES/pam-1.3.1-motd-manpage.patch create mode 100644 SOURCES/pam-1.3.1-namespace-gdm-doc.patch create mode 100644 SOURCES/pam-1.3.1-namespace-mntopts.patch create mode 100644 SOURCES/pam-1.3.1-namespace-protect-dir.patch create mode 100644 SOURCES/pam-1.3.1-noflex.patch create mode 100644 SOURCES/pam-1.3.1-pam-cc-compat.patch create mode 100644 SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch create mode 100644 SOURCES/pam-1.3.1-pam-limits-unlimited-value.patch create mode 100644 SOURCES/pam-1.3.1-pam-misc-configurable.patch create mode 100644 SOURCES/pam-1.3.1-pam-modutil-close-write.patch create mode 100644 SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch create mode 100644 SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch create mode 100644 SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch create mode 100644 SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch create mode 100644 SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch create mode 100644 SOURCES/pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch create mode 100644 SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch create mode 100644 SOURCES/pam-1.3.1-pam-usertype.patch create mode 100644 SOURCES/pam-1.3.1-tty-audit-manfix.patch create mode 100644 SOURCES/pam-1.3.1-unix-default-rounds.patch create mode 100644 SOURCES/pam-1.3.1-unix-enable-bcrypt.patch create mode 100644 SOURCES/pam-1.3.1-unix-improve-logging.patch create mode 100644 SOURCES/pam-1.3.1-wheel-pam_ruser-fallback.patch create mode 100644 SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch create mode 100644 SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch create mode 100644 SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch create mode 100644 SOURCES/pamtmp.conf create mode 100644 SOURCES/password-auth.pamd create mode 100644 SOURCES/postlogin.5 create mode 100644 SOURCES/postlogin.pamd create mode 100644 SOURCES/smartcard-auth.pamd create mode 100644 SOURCES/system-auth.5 create mode 100644 SOURCES/system-auth.pamd create mode 100644 SPECS/pam.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28c7b90 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/Linux-PAM-1.3.1.tar.xz +SOURCES/pam-redhat-0.99.11.tar.bz2 diff --git a/.pam.metadata b/.pam.metadata new file mode 100644 index 0000000..ff5cf70 --- /dev/null +++ b/.pam.metadata @@ -0,0 +1,2 @@ +e89b6d279c9bf8cb495dfc0b3f3931eb50f818e9 SOURCES/Linux-PAM-1.3.1.tar.xz +42206fe8319723ef23ab646b2eab496c86de3f5b SOURCES/pam-redhat-0.99.11.tar.bz2 diff --git a/SOURCES/Linux-PAM-1.3.1.tar.xz.asc b/SOURCES/Linux-PAM-1.3.1.tar.xz.asc new file mode 100644 index 0000000..7057c18 --- /dev/null +++ b/SOURCES/Linux-PAM-1.3.1.tar.xz.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 + +iD8DBQBa/r62bRp/BS5ZJLsRArnKAJ9pGaJHpsEsbOVa5dBQLHYC4DhPuACeJNrg ++DaNc8W13E4Z2ZEUSsgUGe4= +=aSTW +-----END PGP SIGNATURE----- diff --git a/SOURCES/config-util.5 b/SOURCES/config-util.5 new file mode 100644 index 0000000..17d7f8a --- /dev/null +++ b/SOURCES/config-util.5 @@ -0,0 +1,36 @@ +.TH SYSTEM-AUTH 5 "2006 Feb 3" "Red Hat" "Linux-PAM Manual" +.SH NAME + +config-util \- Common PAM configuration file for configuration utilities + +.SH SYNOPSIS +.B /etc/pam.d/config-util +.sp 2 +.SH DESCRIPTION + +The purpose of this configuration file is to provide common +configuration file for all configuration utilities which must be run +from the supervisor account and use the userhelper wrapper application. + +.sp +The +.BR config-util +configuration file is included from all individual configuration +files of such utilities with the help of the +.BR include +directive. +There are not usually any other modules in the individual configuration +files of these utilities. + +.sp +It is possible for example to modify duration of the validity of the +authentication timestamp there. See +.BR pam_timestamp(8) +for details. + +.SH BUGS +.sp 2 +None known. + +.SH "SEE ALSO" +pam(8), config-util(5), pam_timestamp(8) diff --git a/SOURCES/config-util.pamd b/SOURCES/config-util.pamd new file mode 100644 index 0000000..8e70d9a --- /dev/null +++ b/SOURCES/config-util.pamd @@ -0,0 +1,8 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +auth sufficient pam_timestamp.so +auth include system-auth +account required pam_permit.so +session required pam_permit.so +session optional pam_xauth.so +session optional pam_timestamp.so diff --git a/SOURCES/dlopen.sh b/SOURCES/dlopen.sh new file mode 100755 index 0000000..053289a --- /dev/null +++ b/SOURCES/dlopen.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +tempdir=`mktemp -d /tmp/dlopenXXXXXX` +test -n "$tempdir" || exit 1 +cat >> $tempdir/dlopen.c << _EOF +#include +#include +#include +#include +/* Simple program to see if dlopen() would succeed. */ +int main(int argc, char **argv) +{ + int i; + struct stat st; + char buf[PATH_MAX]; + for (i = 1; i < argc; i++) { + if (dlopen(argv[i], RTLD_NOW)) { + fprintf(stdout, "dlopen() of \"%s\" succeeded.\n", + argv[i]); + } else { + snprintf(buf, sizeof(buf), "./%s", argv[i]); + if ((stat(buf, &st) == 0) && dlopen(buf, RTLD_NOW)) { + fprintf(stdout, "dlopen() of \"./%s\" " + "succeeded.\n", argv[i]); + } else { + fprintf(stdout, "dlopen() of \"%s\" failed: " + "%s\n", argv[i], dlerror()); + return 1; + } + } + } + return 0; +} +_EOF + +for arg in $@ ; do + case "$arg" in + "") + ;; + -I*|-D*|-f*|-m*|-g*|-O*|-W*) + cflags="$cflags $arg" + ;; + -l*|-L*) + ldflags="$ldflags $arg" + ;; + /*) + modules="$modules $arg" + ;; + *) + modules="$modules $arg" + ;; + esac +done + +${CC:-gcc} $RPM_OPT_FLAGS $CFLAGS -o $tempdir/dlopen $cflags $tempdir/dlopen.c $ldflags -ldl + +retval=0 +for module in $modules ; do + case "$module" in + "") + ;; + /*) + $tempdir/dlopen "$module" + retval=$? + ;; + *) + $tempdir/dlopen ./"$module" + retval=$? + ;; + esac +done + +rm -f $tempdir/dlopen $tempdir/dlopen.c +rmdir $tempdir +exit $retval diff --git a/SOURCES/fingerprint-auth.pamd b/SOURCES/fingerprint-auth.pamd new file mode 100644 index 0000000..aae6ecc --- /dev/null +++ b/SOURCES/fingerprint-auth.pamd @@ -0,0 +1,19 @@ +#%PAM-1.0 +# This file is auto-generated. +# User changes will be destroyed the next time authselect is run. +auth required pam_env.so +auth sufficient pam_fprintd.so +auth required pam_deny.so + +account required pam_unix.so +account sufficient pam_localuser.so +account sufficient pam_succeed_if.so uid < 500 quiet +account required pam_permit.so + +password required pam_deny.so + +session optional pam_keyinit.so revoke +session required pam_limits.so +-session optional pam_systemd.so +session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid +session required pam_unix.so diff --git a/SOURCES/gpl-2.0.txt b/SOURCES/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/SOURCES/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/SOURCES/other.pamd b/SOURCES/other.pamd new file mode 100644 index 0000000..c286c82 --- /dev/null +++ b/SOURCES/other.pamd @@ -0,0 +1,5 @@ +#%PAM-1.0 +auth required pam_deny.so +account required pam_deny.so +password required pam_deny.so +session required pam_deny.so diff --git a/SOURCES/pam-1.1.0-console-nochmod.patch b/SOURCES/pam-1.1.0-console-nochmod.patch new file mode 100644 index 0000000..e41adad --- /dev/null +++ b/SOURCES/pam-1.1.0-console-nochmod.patch @@ -0,0 +1,26 @@ +diff -up Linux-PAM-1.1.0/modules/pam_console/console.handlers.nochmod Linux-PAM-1.1.0/modules/pam_console/console.handlers +--- Linux-PAM-1.1.0/modules/pam_console/console.handlers.nochmod 2008-12-16 13:37:52.000000000 +0100 ++++ Linux-PAM-1.1.0/modules/pam_console/console.handlers 2009-09-01 17:20:08.000000000 +0200 +@@ -15,5 +15,3 @@ + # touch unlock wait /var/run/console-unlocked + + console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]+\.[0-9]+ :[0-9]+ +-/sbin/pam_console_apply lock logfail wait -t tty -s +-/sbin/pam_console_apply unlock logfail wait -r -t tty -s +diff -up Linux-PAM-1.1.0/modules/pam_console/Makefile.am.nochmod Linux-PAM-1.1.0/modules/pam_console/Makefile.am +--- Linux-PAM-1.1.0/modules/pam_console/Makefile.am.nochmod 2008-12-16 13:37:52.000000000 +0100 ++++ Linux-PAM-1.1.0/modules/pam_console/Makefile.am 2009-09-01 17:42:47.000000000 +0200 +@@ -38,7 +38,6 @@ sbin_PROGRAMS = pam_console_apply + + + secureconf_DATA = console.perms console.handlers +-permsd_DATA = 50-default.perms + + FLEX_OPTS = -Cr + BISON_OPTS = -d +@@ -62,4 +61,5 @@ configfile.c: configfile.tab.c configfil + + install-data-local: + mkdir -p $(DESTDIR)$(secureconfdir)/console.apps ++ mkdir -p $(DESTDIR)$(permsddir) + mkdir -m $(LOCKMODE) -p -p $(DESTDIR)$(LOCKDIR) diff --git a/SOURCES/pam-1.1.0-notally.patch b/SOURCES/pam-1.1.0-notally.patch new file mode 100644 index 0000000..0a98952 --- /dev/null +++ b/SOURCES/pam-1.1.0-notally.patch @@ -0,0 +1,12 @@ +diff -up Linux-PAM-1.1.0/modules/Makefile.am.notally Linux-PAM-1.1.0/modules/Makefile.am +--- Linux-PAM-1.1.0/modules/Makefile.am.notally 2009-07-27 17:39:25.000000000 +0200 ++++ Linux-PAM-1.1.0/modules/Makefile.am 2009-09-01 17:40:16.000000000 +0200 +@@ -10,7 +10,7 @@ SUBDIRS = pam_access pam_cracklib pam_de + 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/SOURCES/pam-1.1.1-console-errmsg.patch b/SOURCES/pam-1.1.1-console-errmsg.patch new file mode 100644 index 0000000..f2fe846 --- /dev/null +++ b/SOURCES/pam-1.1.1-console-errmsg.patch @@ -0,0 +1,12 @@ +diff -up Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c.errmsg Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c +--- Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c.errmsg 2008-12-16 13:37:52.000000000 +0100 ++++ Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c 2014-06-19 13:23:28.948343737 +0200 +@@ -65,7 +65,7 @@ parse_files(void) + on system locale */ + oldlocale = setlocale(LC_COLLATE, "C"); + +- rc = glob(PERMS_GLOB, GLOB_NOCHECK, NULL, &globbuf); ++ rc = glob(PERMS_GLOB, 0, NULL, &globbuf); + setlocale(LC_COLLATE, oldlocale); + if (rc) + return; diff --git a/SOURCES/pam-1.1.3-nouserenv.patch b/SOURCES/pam-1.1.3-nouserenv.patch new file mode 100644 index 0000000..f3a742c --- /dev/null +++ b/SOURCES/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 @@ + + + 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. + + + diff --git a/SOURCES/pam-1.1.6-limits-user.patch b/SOURCES/pam-1.1.6-limits-user.patch new file mode 100644 index 0000000..3c17b78 --- /dev/null +++ b/SOURCES/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: + # + # diff --git a/SOURCES/pam-1.1.8-audit-user-mgmt.patch b/SOURCES/pam-1.1.8-audit-user-mgmt.patch new file mode 100644 index 0000000..277a569 --- /dev/null +++ b/SOURCES/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/SOURCES/pam-1.1.8-full-relro.patch b/SOURCES/pam-1.1.8-full-relro.patch new file mode 100644 index 0000000..07c69e3 --- /dev/null +++ b/SOURCES/pam-1.1.8-full-relro.patch @@ -0,0 +1,88 @@ +diff -up Linux-PAM-1.1.8/modules/pam_console/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_console/Makefile.am +--- Linux-PAM-1.1.8/modules/pam_console/Makefile.am.relro 2014-08-13 16:02:49.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_console/Makefile.am 2014-09-10 17:14:33.245554314 +0200 +@@ -33,6 +33,8 @@ pam_console_la_LIBADD = -L$(top_builddir + + pam_console_apply_LDADD = -L$(top_builddir)/libpam -lpam + ++pam_console_apply_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ ++ + securelib_LTLIBRARIES = pam_console.la + sbin_PROGRAMS = pam_console_apply + +@@ -47,7 +49,7 @@ pam_console_apply_SOURCES = pam_console_ + configfile.c configfile.h hashtable.c hashtable.h hashtable_private.h + + pam_console_la_CFLAGS = $(AM_CFLAGS) +-pam_console_apply_CFLAGS = $(AM_CFLAGS) ++pam_console_apply_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ + + configfile.tab.c: configfile.y + $(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $< +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/SOURCES/pam-1.2.0-redhat-modules.patch b/SOURCES/pam-1.2.0-redhat-modules.patch new file mode 100644 index 0000000..8a66134 --- /dev/null +++ b/SOURCES/pam-1.2.0-redhat-modules.patch @@ -0,0 +1,23 @@ +diff -up Linux-PAM-1.2.0/configure.ac.redhat-modules Linux-PAM-1.2.0/configure.ac +--- Linux-PAM-1.2.0/configure.ac.redhat-modules 2015-03-25 16:50:10.000000000 +0100 ++++ Linux-PAM-1.2.0/configure.ac 2015-05-15 15:46:50.996074677 +0200 +@@ -616,6 +616,8 @@ 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 \ +diff -up Linux-PAM-1.2.0/modules/Makefile.am.redhat-modules Linux-PAM-1.2.0/modules/Makefile.am +--- Linux-PAM-1.2.0/modules/Makefile.am.redhat-modules 2015-03-24 13:02:32.000000000 +0100 ++++ Linux-PAM-1.2.0/modules/Makefile.am 2015-05-15 15:46:50.995074654 +0200 +@@ -3,6 +3,7 @@ + # + + SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ ++ pam_chroot pam_console pam_postgresok \ + 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 \ diff --git a/SOURCES/pam-1.2.0-unix-no-fallback.patch b/SOURCES/pam-1.2.0-unix-no-fallback.patch new file mode 100644 index 0000000..6295da7 --- /dev/null +++ b/SOURCES/pam-1.2.0-unix-no-fallback.patch @@ -0,0 +1,73 @@ +diff -up Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml.no-fallback Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml +--- Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml.no-fallback 2015-04-27 16:38:03.000000000 +0200 ++++ Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml 2015-05-15 15:54:21.524440864 +0200 +@@ -284,11 +284,10 @@ + + + When a user changes their password next, +- encrypt it with the SHA256 algorithm. If the +- SHA256 algorithm is not known to the ++ encrypt it with the SHA256 algorithm. The ++ SHA256 algorithm must be supported by the + crypt3 +- function, +- fall back to MD5. ++ function. + + + +@@ -299,11 +298,10 @@ + + + When a user changes their password next, +- encrypt it with the SHA512 algorithm. If the +- SHA512 algorithm is not known to the ++ encrypt it with the SHA512 algorithm. The ++ SHA512 algorithm must be supported by the + crypt3 +- function, +- fall back to MD5. ++ function. + + + +@@ -314,11 +312,10 @@ + + + When a user changes their password next, +- encrypt it with the blowfish algorithm. If the +- blowfish algorithm is not known to the ++ encrypt it with the blowfish algorithm. The ++ blowfish algorithm must be supported by the + crypt3 +- function, +- fall back to MD5. ++ function. + + + +diff -up Linux-PAM-1.2.0/modules/pam_unix/passverify.c.no-fallback Linux-PAM-1.2.0/modules/pam_unix/passverify.c +--- Linux-PAM-1.2.0/modules/pam_unix/passverify.c.no-fallback 2015-05-15 15:54:21.525440887 +0200 ++++ Linux-PAM-1.2.0/modules/pam_unix/passverify.c 2015-05-15 15:57:23.138613273 +0200 +@@ -437,10 +437,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_BLOWFISH_PASS, ctrl) ? "blowfish" : + on(UNIX_SHA256_PASS, ctrl) ? "sha256" : + on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); +@@ -450,7 +449,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/SOURCES/pam-1.2.1-console-devname.patch b/SOURCES/pam-1.2.1-console-devname.patch new file mode 100644 index 0000000..5e03b40 --- /dev/null +++ b/SOURCES/pam-1.2.1-console-devname.patch @@ -0,0 +1,9 @@ +diff -up Linux-PAM-1.2.1/modules/pam_console/console.handlers.devname Linux-PAM-1.2.1/modules/pam_console/console.handlers +--- Linux-PAM-1.2.1/modules/pam_console/console.handlers.devname 2015-10-16 14:15:48.000000000 +0200 ++++ Linux-PAM-1.2.1/modules/pam_console/console.handlers 2016-02-05 17:47:26.056787517 +0100 +@@ -14,4 +14,4 @@ + # echo lock wait Locking console for user on tty + # touch unlock wait /var/run/console-unlocked + +-console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]+\.[0-9]+ :[0-9]+ ++console consoledevs /dev/tty[0-9][0-9]* tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]+\.[0-9]+ :[0-9]+ diff --git a/SOURCES/pam-1.2.1-faillock-admin-group.patch b/SOURCES/pam-1.2.1-faillock-admin-group.patch new file mode 100644 index 0000000..8bd1384 --- /dev/null +++ b/SOURCES/pam-1.2.1-faillock-admin-group.patch @@ -0,0 +1,133 @@ +diff -up Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c.admin-group Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c +--- Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c.admin-group 2016-04-04 16:37:38.696260359 +0200 ++++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c 2017-08-21 16:40:01.624706864 +0200 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2010 Tomas Mraz ++ * Copyright (c) 2010, 2017 Tomas Mraz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -78,9 +78,11 @@ struct options { + unsigned int root_unlock_time; + const char *dir; + const char *user; ++ const char *admin_group; + int failures; + uint64_t latest_time; + uid_t uid; ++ int is_admin; + uint64_t now; + }; + +@@ -152,6 +154,9 @@ args_parse(pam_handle_t *pamh, int argc, + opts->root_unlock_time = temp; + } + } ++ else if (strncmp(argv[i], "admin_group=", 12) == 0) { ++ opts->admin_group = argv[i] + 12; ++ } + else if (strcmp(argv[i], "preauth") == 0) { + opts->action = FAILLOCK_ACTION_PREAUTH; + } +@@ -209,6 +214,17 @@ static int get_pam_user(pam_handle_t *pa + } + opts->user = user; + opts->uid = pwd->pw_uid; ++ ++ if (pwd->pw_uid == 0) { ++ opts->is_admin = 1; ++ return PAM_SUCCESS; ++ } ++ ++ if (opts->admin_group && *opts->admin_group) { ++ opts->is_admin = pam_modutil_user_in_group_uid_nam(pamh, ++ pwd->pw_uid, opts->admin_group); ++ } ++ + return PAM_SUCCESS; + } + +@@ -239,7 +255,7 @@ check_tally(pam_handle_t *pamh, struct o + return PAM_SYSTEM_ERR; + } + +- if (opts->uid == 0 && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ if (opts->is_admin && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { + return PAM_SUCCESS; + } + +@@ -262,13 +278,9 @@ check_tally(pam_handle_t *pamh, struct o + + opts->failures = failures; + +- if (opts->uid == 0 && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { +- return PAM_SUCCESS; +- } +- + if (opts->deny && failures >= opts->deny) { +- if ((opts->uid && opts->unlock_time && latest_time + opts->unlock_time < opts->now) || +- (!opts->uid && opts->root_unlock_time && latest_time + opts->root_unlock_time < opts->now)) { ++ if ((!opts->is_admin && opts->unlock_time && latest_time + opts->unlock_time < opts->now) || ++ (opts->is_admin && opts->root_unlock_time && latest_time + opts->root_unlock_time < opts->now)) { + #ifdef HAVE_LIBAUDIT + if (opts->action != FAILLOCK_ACTION_PREAUTH) { /* do not audit in preauth */ + char buf[64]; +@@ -401,7 +413,7 @@ write_tally(pam_handle_t *pamh, struct o + audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf, + NULL, NULL, NULL, 1); + +- if (opts->uid != 0 || (opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ if (!opts->is_admin || (opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { + audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_LOCK, buf, + NULL, NULL, NULL, 1); + } +@@ -425,11 +437,11 @@ faillock_message(pam_handle_t *pamh, str + int64_t left; + + if (!(opts->flags & FAILLOCK_FLAG_SILENT)) { +- if (opts->uid) { +- left = opts->latest_time + opts->unlock_time - opts->now; ++ if (opts->is_admin) { ++ left = opts->latest_time + opts->root_unlock_time - opts->now; + } + else { +- left = opts->latest_time + opts->root_unlock_time - opts->now; ++ left = opts->latest_time + opts->unlock_time - opts->now; + } + + if (left > 0) { +diff -up Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml.admin-group Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml +--- Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml.admin-group 2016-05-06 15:24:10.328281818 +0200 ++++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml 2017-08-21 16:16:09.448033843 +0200 +@@ -40,6 +40,9 @@ + root_unlock_time=n + + ++ admin_group=name ++ ++ + audit + + +@@ -243,6 +246,20 @@ + + + ++ ++ ++ ++ ++ ++ ++ If a group name is specified with this option, members ++ of the group will be handled by this module the same as ++ the root account (the options ++ and will apply to them. ++ By default the option is not set. ++ ++ ++ + + + diff --git a/SOURCES/pam-1.2.1-faillock.patch b/SOURCES/pam-1.2.1-faillock.patch new file mode 100644 index 0000000..7a4209c --- /dev/null +++ b/SOURCES/pam-1.2.1-faillock.patch @@ -0,0 +1,1759 @@ +diff -up Linux-PAM-1.2.1/configure.ac.faillock Linux-PAM-1.2.1/configure.ac +--- Linux-PAM-1.2.1/configure.ac.faillock 2015-06-25 10:42:21.477374752 +0200 ++++ Linux-PAM-1.2.1/configure.ac 2015-06-25 10:42:21.501375246 +0200 +@@ -621,7 +621,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefil + 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.2.1/doc/sag/pam_faillock.xml.faillock Linux-PAM-1.2.1/doc/sag/pam_faillock.xml +--- Linux-PAM-1.2.1/doc/sag/pam_faillock.xml.faillock 2015-06-25 10:42:21.482374855 +0200 ++++ Linux-PAM-1.2.1/doc/sag/pam_faillock.xml 2015-06-25 10:42:21.482374855 +0200 +@@ -0,0 +1,38 @@ ++ ++ ++
++ pam_faillock - temporarily locking access based on failed authentication attempts during an interval ++ ++ ++ ++ ++ ++ ++
++ ++
++
++ ++
++
++ ++
++
++ ++
++
++ ++
++
++ ++
++
+diff -up Linux-PAM-1.2.1/modules/Makefile.am.faillock Linux-PAM-1.2.1/modules/Makefile.am +--- Linux-PAM-1.2.1/modules/Makefile.am.faillock 2015-06-25 10:42:21.480374814 +0200 ++++ Linux-PAM-1.2.1/modules/Makefile.am 2015-06-25 10:42:21.482374855 +0200 +@@ -3,7 +3,7 @@ + # + + SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ +- pam_chroot pam_console pam_postgresok \ ++ 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 \ +diff -up Linux-PAM-1.2.1/modules/pam_faillock/faillock.c.faillock Linux-PAM-1.2.1/modules/pam_faillock/faillock.c +--- Linux-PAM-1.2.1/modules/pam_faillock/faillock.c.faillock 2015-06-25 10:42:21.482374855 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/faillock.c 2015-06-25 10:42:21.482374855 +0200 +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "faillock.h" ++ ++int ++open_tally (const char *dir, const char *user, uid_t uid, int create) ++{ ++ char *path; ++ int flags = O_RDWR; ++ int fd; ++ ++ if (strstr(user, "../") != NULL) ++ /* just a defensive programming as the user must be a ++ * valid user on the system anyway ++ */ ++ return -1; ++ path = malloc(strlen(dir) + strlen(user) + 2); ++ if (path == NULL) ++ return -1; ++ ++ strcpy(path, dir); ++ if (*dir && dir[strlen(dir) - 1] != '/') { ++ strcat(path, "/"); ++ } ++ strcat(path, user); ++ ++ if (create) { ++ flags |= O_CREAT; ++ } ++ ++ fd = open(path, flags, 0600); ++ ++ free(path); ++ ++ if (fd != -1) { ++ struct stat st; ++ ++ while (flock(fd, LOCK_EX) == -1 && errno == EINTR); ++ if (fstat(fd, &st) == 0) { ++ if (st.st_uid != uid) { ++ fchown(fd, uid, -1); ++ } ++ } ++ } ++ ++ return fd; ++} ++ ++#define CHUNK_SIZE (64 * sizeof(struct tally)) ++#define MAX_RECORDS 1024 ++ ++int ++read_tally(int fd, struct tally_data *tallies) ++{ ++ void *data = NULL, *newdata; ++ unsigned int count = 0; ++ ssize_t chunk = 0; ++ ++ do { ++ newdata = realloc(data, count * sizeof(struct tally) + CHUNK_SIZE); ++ if (newdata == NULL) { ++ free(data); ++ return -1; ++ } ++ ++ data = newdata; ++ ++ chunk = pam_modutil_read(fd, (char *)data + count * sizeof(struct tally), CHUNK_SIZE); ++ if (chunk < 0) { ++ free(data); ++ return -1; ++ } ++ ++ count += chunk/sizeof(struct tally); ++ ++ if (count >= MAX_RECORDS) ++ break; ++ } ++ while (chunk == CHUNK_SIZE); ++ ++ tallies->records = data; ++ tallies->count = count; ++ ++ return 0; ++} ++ ++int ++update_tally(int fd, struct tally_data *tallies) ++{ ++ void *data = tallies->records; ++ unsigned int count = tallies->count; ++ ssize_t chunk; ++ ++ if (tallies->count > MAX_RECORDS) { ++ data = tallies->records + (count - MAX_RECORDS); ++ count = MAX_RECORDS; ++ } ++ ++ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { ++ return -1; ++ } ++ ++ chunk = pam_modutil_write(fd, data, count * sizeof(struct tally)); ++ ++ if (chunk != (ssize_t)(count * sizeof(struct tally))) { ++ return -1; ++ } ++ ++ if (ftruncate(fd, count * sizeof(struct tally)) == -1) ++ return -1; ++ ++ return 0; ++} +diff -up Linux-PAM-1.2.1/modules/pam_faillock/faillock.h.faillock Linux-PAM-1.2.1/modules/pam_faillock/faillock.h +--- Linux-PAM-1.2.1/modules/pam_faillock/faillock.h.faillock 2015-06-25 10:42:21.482374855 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/faillock.h 2015-06-25 10:42:21.482374855 +0200 +@@ -0,0 +1,73 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * ++ * 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. ++ */ ++ ++/* ++ * faillock.h - authentication failure data file record structure ++ * ++ * Each record in the file represents an instance of login failure of ++ * the user at the recorded time ++ */ ++ ++ ++#ifndef _FAILLOCK_H ++#define _FAILLOCK_H ++ ++#include ++#include ++ ++#define TALLY_STATUS_VALID 0x1 /* the tally file entry is valid */ ++#define TALLY_STATUS_RHOST 0x2 /* the source is rhost */ ++#define TALLY_STATUS_TTY 0x4 /* the source is tty - if both TALLY_FLAG_RHOST and TALLY_FLAG_TTY are not set the source is service */ ++ ++struct tally { ++ char source[52]; /* rhost or tty of the login failure (not necessarily NULL terminated) */ ++ uint16_t reserved; /* reserved for future use */ ++ uint16_t status; /* record status */ ++ uint64_t time; /* time of the login failure */ ++}; ++/* 64 bytes per entry */ ++ ++struct tally_data { ++ struct tally *records; /* array of tallies */ ++ unsigned int count; /* number of records */ ++}; ++ ++#define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock" ++ ++int open_tally(const char *dir, const char *user, uid_t uid, int create); ++int read_tally(int fd, struct tally_data *tallies); ++int update_tally(int fd, struct tally_data *tallies); ++#endif ++ +diff -up Linux-PAM-1.2.1/modules/pam_faillock/faillock.8.xml.faillock Linux-PAM-1.2.1/modules/pam_faillock/faillock.8.xml +--- Linux-PAM-1.2.1/modules/pam_faillock/faillock.8.xml.faillock 2015-06-25 10:42:21.482374855 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/faillock.8.xml 2015-06-25 10:42:21.482374855 +0200 +@@ -0,0 +1,123 @@ ++ ++ ++ ++ ++ ++ ++ faillock ++ 8 ++ Linux-PAM Manual ++ ++ ++ ++ faillock ++ Tool for displaying and modifying the authentication failure record files ++ ++ ++ ++ ++ faillock ++ ++ --dir /path/to/tally-directory ++ ++ ++ --user username ++ ++ ++ --reset ++ ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ ++ The pam_faillock.so module maintains a list of ++ failed authentication attempts per user during a specified interval ++ and locks the account in case there were more than ++ deny consecutive failed authentications. ++ It stores the failure records into per-user files in the tally ++ directory. ++ ++ ++ The faillock command is an application which ++ can be used to examine and modify the contents of the ++ the tally files. It can display the recent failed authentication ++ attempts of the username or clear the tally ++ files of all or individual usernames. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ The directory where the user files with the failure records are kept. The ++ default is /var/run/faillock. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The user whose failure records should be displayed or cleared. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Instead of displaying the user's failure records, clear them. ++ ++ ++ ++ ++ ++ ++ ++ FILES ++ ++ ++ /var/run/faillock/* ++ ++ the files logging the authentication failures for users ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ pam_faillock8 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ faillock was written by Tomas Mraz. ++ ++ ++ ++ +diff -up Linux-PAM-1.2.1/modules/pam_faillock/main.c.faillock Linux-PAM-1.2.1/modules/pam_faillock/main.c +--- Linux-PAM-1.2.1/modules/pam_faillock/main.c.faillock 2015-06-25 10:42:21.482374855 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/main.c 2015-06-25 10:42:21.503375287 +0200 +@@ -0,0 +1,232 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_LIBAUDIT ++#include ++#endif ++ ++#include "faillock.h" ++ ++struct options { ++ unsigned int reset; ++ const char *dir; ++ const char *user; ++ const char *progname; ++}; ++ ++static int ++args_parse(int argc, char **argv, struct options *opts) ++{ ++ int i; ++ memset(opts, 0, sizeof(*opts)); ++ ++ opts->dir = FAILLOCK_DEFAULT_TALLYDIR; ++ opts->progname = argv[0]; ++ ++ for (i = 1; i < argc; ++i) { ++ ++ if (strcmp(argv[i], "--dir") == 0) { ++ ++i; ++ if (i >= argc || strlen(argv[i]) == 0) { ++ fprintf(stderr, "%s: No directory supplied.\n", argv[0]); ++ return -1; ++ } ++ opts->dir = argv[i]; ++ } ++ else if (strcmp(argv[i], "--user") == 0) { ++ ++i; ++ if (i >= argc || strlen(argv[i]) == 0) { ++ fprintf(stderr, "%s: No user name supplied.\n", argv[0]); ++ return -1; ++ } ++ opts->user = argv[i]; ++ } ++ else if (strcmp(argv[i], "--reset") == 0) { ++ opts->reset = 1; ++ } ++ else { ++ fprintf(stderr, "%s: Unknown option: %s\n", argv[0], argv[i]); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static void ++usage(const char *progname) ++{ ++ fprintf(stderr, _("Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n"), ++ progname); ++} ++ ++static int ++do_user(struct options *opts, const char *user) ++{ ++ int fd; ++ int rv; ++ struct tally_data tallies; ++ struct passwd *pwd; ++ ++ pwd = getpwnam(user); ++ ++ fd = open_tally(opts->dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); ++ ++ if (fd == -1) { ++ if (errno == ENOENT) { ++ return 0; ++ } ++ else { ++ fprintf(stderr, "%s: Error opening the tally file for %s:", ++ opts->progname, user); ++ perror(NULL); ++ return 3; ++ } ++ } ++ if (opts->reset) { ++#ifdef HAVE_LIBAUDIT ++ int audit_fd; ++#endif ++ ++ while ((rv=ftruncate(fd, 0)) == -1 && errno == EINTR); ++ if (rv == -1) { ++ fprintf(stderr, "%s: Error clearing the tally file for %s:", ++ opts->progname, user); ++ perror(NULL); ++#ifdef HAVE_LIBAUDIT ++ } ++ if ((audit_fd=audit_open()) >= 0) { ++ ++ if (pwd != NULL) { ++ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL, ++ "faillock-reset", NULL, pwd->pw_uid, NULL, NULL, NULL, rv == 0); ++ } ++ close(audit_fd); ++ } ++ if (rv == -1) { ++#endif ++ close(fd); ++ return 4; ++ } ++ } ++ else { ++ unsigned int i; ++ ++ memset(&tallies, 0, sizeof(tallies)); ++ if ((rv=read_tally(fd, &tallies)) == -1) { ++ fprintf(stderr, "%s: Error reading the tally file for %s:", ++ opts->progname, user); ++ perror(NULL); ++ close(fd); ++ return 5; ++ } ++ ++ printf("%s:\n", user); ++ printf("%-19s %-5s %-48s %-5s\n", "When", "Type", "Source", "Valid"); ++ ++ for (i = 0; i < tallies.count; i++) { ++ struct tm *tm; ++ char timebuf[80]; ++ uint16_t status = tallies.records[i].status; ++ time_t when = tallies.records[i].time; ++ ++ tm = localtime(&when); ++ strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm); ++ printf("%-19s %-5s %-52.52s %s\n", timebuf, ++ status & TALLY_STATUS_RHOST ? "RHOST" : (status & TALLY_STATUS_TTY ? "TTY" : "SVC"), ++ tallies.records[i].source, status & TALLY_STATUS_VALID ? "V":"I"); ++ } ++ free(tallies.records); ++ } ++ close(fd); ++ return 0; ++} ++ ++static int ++do_allusers(struct options *opts) ++{ ++ struct dirent **userlist; ++ int rv, i; ++ ++ rv = scandir(opts->dir, &userlist, NULL, alphasort); ++ if (rv < 0) { ++ fprintf(stderr, "%s: Error reading tally directory: ", opts->progname); ++ perror(NULL); ++ return 2; ++ } ++ ++ for (i = 0; i < rv; i++) { ++ if (userlist[i]->d_name[0] == '.') { ++ if ((userlist[i]->d_name[1] == '.' && userlist[i]->d_name[2] == '\0') || ++ userlist[i]->d_name[1] == '\0') ++ continue; ++ } ++ do_user(opts, userlist[i]->d_name); ++ free(userlist[i]); ++ } ++ free(userlist); ++ ++ return 0; ++} ++ ++ ++/*-----------------------------------------------------------------------*/ ++int ++main (int argc, char *argv[]) ++{ ++ struct options opts; ++ ++ if (args_parse(argc, argv, &opts)) { ++ usage(argv[0]); ++ return 1; ++ } ++ ++ if (opts.user == NULL) { ++ return do_allusers(&opts); ++ } ++ ++ return do_user(&opts, opts.user); ++} ++ +diff -up Linux-PAM-1.2.1/modules/pam_faillock/Makefile.am.faillock Linux-PAM-1.2.1/modules/pam_faillock/Makefile.am +--- Linux-PAM-1.2.1/modules/pam_faillock/Makefile.am.faillock 2015-06-25 10:42:21.482374855 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/Makefile.am 2015-06-25 10:42:21.494375102 +0200 +@@ -0,0 +1,44 @@ ++# ++# Copyright (c) 2005, 2006, 2007, 2009 Thorsten Kukuk ++# Copyright (c) 2008 Red Hat, Inc. ++# Copyright (c) 2010 Tomas Mraz ++# ++ ++CLEANFILES = *~ ++MAINTAINERCLEANFILES = $(MANS) README ++ ++EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_faillock ++ ++man_MANS = pam_faillock.8 faillock.8 ++XMLS = README.xml pam_faillock.8.xml faillock.8.xml ++ ++TESTS = tst-pam_faillock ++ ++securelibdir = $(SECUREDIR) ++secureconfdir = $(SCONFIGDIR) ++ ++noinst_HEADERS = faillock.h ++ ++faillock_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include @PIE_CFLAGS@ ++pam_faillock_la_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include ++ ++pam_faillock_la_LDFLAGS = -no-undefined -avoid-version -module ++pam_faillock_la_LIBADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT) ++if HAVE_VERSIONING ++ pam_faillock_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map ++endif ++ ++faillock_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ ++faillock_LDADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT) ++ ++securelib_LTLIBRARIES = pam_faillock.la ++sbin_PROGRAMS = faillock ++ ++pam_faillock_la_SOURCES = pam_faillock.c faillock.c ++faillock_SOURCES = main.c faillock.c ++ ++if ENABLE_REGENERATE_MAN ++noinst_DATA = README ++README: pam_faillock.8.xml ++-include $(top_srcdir)/Make.xml.rules ++endif +diff -up Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.c.faillock Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.c +--- Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.c.faillock 2015-06-25 10:42:21.483374875 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.c 2015-10-16 14:07:38.451616869 +0200 +@@ -0,0 +1,571 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_LIBAUDIT ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include "faillock.h" ++ ++#define PAM_SM_AUTH ++#define PAM_SM_ACCOUNT ++ ++#define FAILLOCK_ACTION_PREAUTH 0 ++#define FAILLOCK_ACTION_AUTHSUCC 1 ++#define FAILLOCK_ACTION_AUTHFAIL 2 ++ ++#define FAILLOCK_FLAG_DENY_ROOT 0x1 ++#define FAILLOCK_FLAG_AUDIT 0x2 ++#define FAILLOCK_FLAG_SILENT 0x4 ++#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 ++#define FAILLOCK_FLAG_UNLOCKED 0x10 ++ ++#define MAX_TIME_INTERVAL 604800 /* 7 days */ ++ ++struct options { ++ unsigned int action; ++ unsigned int flags; ++ unsigned short deny; ++ unsigned int fail_interval; ++ unsigned int unlock_time; ++ unsigned int root_unlock_time; ++ const char *dir; ++ const char *user; ++ int failures; ++ uint64_t latest_time; ++ uid_t uid; ++ uint64_t now; ++}; ++ ++static void ++args_parse(pam_handle_t *pamh, int argc, const char **argv, ++ int flags, struct options *opts) ++{ ++ int i; ++ memset(opts, 0, sizeof(*opts)); ++ ++ opts->dir = FAILLOCK_DEFAULT_TALLYDIR; ++ opts->deny = 3; ++ opts->fail_interval = 900; ++ opts->unlock_time = 600; ++ opts->root_unlock_time = MAX_TIME_INTERVAL+1; ++ ++ for (i = 0; i < argc; ++i) { ++ ++ if (strncmp(argv[i], "dir=", 4) == 0) { ++ if (argv[i][4] != '/') { ++ pam_syslog(pamh, LOG_ERR, ++ "Tally directory is not absolute path (%s); keeping default", argv[i]); ++ } else { ++ opts->dir = argv[i]+4; ++ } ++ } ++ else if (strncmp(argv[i], "deny=", 5) == 0) { ++ if (sscanf(argv[i]+5, "%hu", &opts->deny) != 1) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for deny argument"); ++ } ++ } ++ else if (strncmp(argv[i], "fail_interval=", 14) == 0) { ++ unsigned int temp; ++ if (sscanf(argv[i]+14, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for fail_interval argument"); ++ } else { ++ opts->fail_interval = temp; ++ } ++ } ++ else if (strncmp(argv[i], "unlock_time=", 12) == 0) { ++ unsigned int temp; ++ ++ if (strcmp(argv[i]+12, "never") == 0) { ++ opts->unlock_time = 0; ++ } ++ else if (sscanf(argv[i]+12, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for unlock_time argument"); ++ } ++ else { ++ opts->unlock_time = temp; ++ } ++ } ++ else if (strncmp(argv[i], "root_unlock_time=", 17) == 0) { ++ unsigned int temp; ++ ++ if (strcmp(argv[i]+17, "never") == 0) { ++ opts->root_unlock_time = 0; ++ } ++ else if (sscanf(argv[i]+17, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for root_unlock_time argument"); ++ } else { ++ opts->root_unlock_time = temp; ++ } ++ } ++ else if (strcmp(argv[i], "preauth") == 0) { ++ opts->action = FAILLOCK_ACTION_PREAUTH; ++ } ++ else if (strcmp(argv[i], "authfail") == 0) { ++ opts->action = FAILLOCK_ACTION_AUTHFAIL; ++ } ++ else if (strcmp(argv[i], "authsucc") == 0) { ++ opts->action = FAILLOCK_ACTION_AUTHSUCC; ++ } ++ else if (strcmp(argv[i], "even_deny_root") == 0) { ++ opts->flags |= FAILLOCK_FLAG_DENY_ROOT; ++ } ++ else if (strcmp(argv[i], "audit") == 0) { ++ opts->flags |= FAILLOCK_FLAG_AUDIT; ++ } ++ else if (strcmp(argv[i], "silent") == 0) { ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++ } ++ else if (strcmp(argv[i], "no_log_info") == 0) { ++ opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; ++ } ++ else { ++ pam_syslog(pamh, LOG_ERR, "Unknown option: %s", argv[i]); ++ } ++ } ++ ++ if (opts->root_unlock_time == MAX_TIME_INTERVAL+1) ++ opts->root_unlock_time = opts->unlock_time; ++ if (flags & PAM_SILENT) ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++} ++ ++static int get_pam_user(pam_handle_t *pamh, struct options *opts) ++{ ++ const char *user; ++ int rv; ++ struct passwd *pwd; ++ ++ if ((rv=pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { ++ return rv; ++ } ++ ++ if (*user == '\0') { ++ return PAM_IGNORE; ++ } ++ ++ if ((pwd=pam_modutil_getpwnam(pamh, user)) == NULL) { ++ if (opts->flags & FAILLOCK_FLAG_AUDIT) { ++ pam_syslog(pamh, LOG_ERR, "User unknown: %s", user); ++ } ++ else { ++ pam_syslog(pamh, LOG_ERR, "User unknown"); ++ } ++ return PAM_IGNORE; ++ } ++ opts->user = user; ++ opts->uid = pwd->pw_uid; ++ return PAM_SUCCESS; ++} ++ ++static int ++check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies, int *fd) ++{ ++ int tfd; ++ unsigned int i; ++ uint64_t latest_time; ++ int failures; ++ ++ opts->now = time(NULL); ++ ++ tfd = open_tally(opts->dir, opts->user, opts->uid, 0); ++ ++ *fd = tfd; ++ ++ if (tfd == -1) { ++ if (errno == EACCES || errno == ENOENT) { ++ return PAM_SUCCESS; ++ } ++ pam_syslog(pamh, LOG_ERR, "Error opening the tally file for %s: %m", opts->user); ++ return PAM_SYSTEM_ERR; ++ } ++ ++ if (read_tally(tfd, tallies) != 0) { ++ pam_syslog(pamh, LOG_ERR, "Error reading the tally file for %s: %m", opts->user); ++ return PAM_SYSTEM_ERR; ++ } ++ ++ if (opts->uid == 0 && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ return PAM_SUCCESS; ++ } ++ ++ latest_time = 0; ++ for(i = 0; i < tallies->count; i++) { ++ if ((tallies->records[i].status & TALLY_STATUS_VALID) && ++ tallies->records[i].time > latest_time) ++ latest_time = tallies->records[i].time; ++ } ++ ++ opts->latest_time = latest_time; ++ ++ failures = 0; ++ for(i = 0; i < tallies->count; i++) { ++ if ((tallies->records[i].status & TALLY_STATUS_VALID) && ++ latest_time - tallies->records[i].time < opts->fail_interval) { ++ ++failures; ++ } ++ } ++ ++ opts->failures = failures; ++ ++ if (opts->uid == 0 && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ return PAM_SUCCESS; ++ } ++ ++ if (opts->deny && failures >= opts->deny) { ++ if ((opts->uid && opts->unlock_time && latest_time + opts->unlock_time < opts->now) || ++ (!opts->uid && opts->root_unlock_time && latest_time + opts->root_unlock_time < opts->now)) { ++#ifdef HAVE_LIBAUDIT ++ if (opts->action != FAILLOCK_ACTION_PREAUTH) { /* do not audit in preauth */ ++ char buf[64]; ++ int audit_fd; ++ const void *rhost = NULL, *tty = NULL; ++ ++ audit_fd = audit_open(); ++ /* If there is an error & audit support is in the kernel report error */ ++ if ((audit_fd < 0) && !(errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT)) ++ return PAM_SYSTEM_ERR; ++ ++ (void)pam_get_item(pamh, PAM_TTY, &tty); ++ (void)pam_get_item(pamh, PAM_RHOST, &rhost); ++ snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid); ++ audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf, ++ rhost, NULL, tty, 1); ++ } ++#endif ++ opts->flags |= FAILLOCK_FLAG_UNLOCKED; ++ return PAM_SUCCESS; ++ } ++ return PAM_AUTH_ERR; ++ } ++ return PAM_SUCCESS; ++} ++ ++static void ++reset_tally(pam_handle_t *pamh, struct options *opts, int *fd) ++{ ++ int rv; ++ ++ if (*fd == -1) { ++ *fd = open_tally(opts->dir, opts->user, opts->uid, 1); ++ } ++ else { ++ while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR); ++ if (rv == -1) { ++ pam_syslog(pamh, LOG_ERR, "Error clearing the tally file for %s: %m", opts->user); ++ } ++ } ++} ++ ++static int ++write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies, int *fd) ++{ ++ struct tally *records; ++ unsigned int i; ++ int failures; ++ unsigned int oldest; ++ uint64_t oldtime; ++ const void *source = NULL; ++ ++ if (*fd == -1) { ++ *fd = open_tally(opts->dir, opts->user, opts->uid, 1); ++ } ++ if (*fd == -1) { ++ if (errno == EACCES) { ++ return PAM_SUCCESS; ++ } ++ pam_syslog(pamh, LOG_ERR, "Error opening the tally file for %s: %m", opts->user); ++ return PAM_SYSTEM_ERR; ++ } ++ ++ oldtime = 0; ++ oldest = 0; ++ failures = 0; ++ ++ for (i = 0; i < tallies->count; ++i) { ++ if (tallies->records[i].time < oldtime) { ++ oldtime = tallies->records[i].time; ++ oldest = i; ++ } ++ if (opts->flags & FAILLOCK_FLAG_UNLOCKED || ++ opts->now - tallies->records[i].time >= opts->fail_interval ) { ++ tallies->records[i].status &= ~TALLY_STATUS_VALID; ++ } else { ++ ++failures; ++ } ++ } ++ ++ if (oldest >= tallies->count || (tallies->records[oldest].status & TALLY_STATUS_VALID)) { ++ oldest = tallies->count; ++ ++ if ((records=realloc(tallies->records, (oldest+1) * sizeof (*tallies->records))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "Error allocating memory for tally records: %m"); ++ return PAM_BUF_ERR; ++ } ++ ++ ++tallies->count; ++ tallies->records = records; ++ } ++ ++ memset(&tallies->records[oldest], 0, sizeof (*tallies->records)); ++ ++ tallies->records[oldest].status = TALLY_STATUS_VALID; ++ if (pam_get_item(pamh, PAM_RHOST, &source) != PAM_SUCCESS || source == NULL) { ++ if (pam_get_item(pamh, PAM_TTY, &source) != PAM_SUCCESS || source == NULL) { ++ if (pam_get_item(pamh, PAM_SERVICE, &source) != PAM_SUCCESS || source == NULL) { ++ source = ""; ++ } ++ } ++ else { ++ tallies->records[oldest].status |= TALLY_STATUS_TTY; ++ } ++ } ++ else { ++ tallies->records[oldest].status |= TALLY_STATUS_RHOST; ++ } ++ ++ strncpy(tallies->records[oldest].source, source, sizeof(tallies->records[oldest].source)); ++ /* source does not have to be null terminated */ ++ ++ tallies->records[oldest].time = opts->now; ++ ++ ++failures; ++ ++ if (opts->deny && failures == opts->deny) { ++#ifdef HAVE_LIBAUDIT ++ char buf[64]; ++ int audit_fd; ++ ++ audit_fd = audit_open(); ++ /* If there is an error & audit support is in the kernel report error */ ++ if ((audit_fd < 0) && !(errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT)) ++ return PAM_SYSTEM_ERR; ++ ++ snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid); ++ audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf, ++ NULL, NULL, NULL, 1); ++ ++ if (opts->uid != 0 || (opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_LOCK, buf, ++ NULL, NULL, NULL, 1); ++ } ++ close(audit_fd); ++#endif ++ if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO)) { ++ pam_syslog(pamh, LOG_INFO, "Consecutive login failures for user %s account temporarily locked", ++ opts->user); ++ } ++ } ++ ++ if (update_tally(*fd, tallies) == 0) ++ return PAM_SUCCESS; ++ ++ return PAM_SYSTEM_ERR; ++} ++ ++static void ++faillock_message(pam_handle_t *pamh, struct options *opts) ++{ ++ int64_t left; ++ ++ if (!(opts->flags & FAILLOCK_FLAG_SILENT)) { ++ if (opts->uid) { ++ left = opts->latest_time + opts->unlock_time - opts->now; ++ } ++ else { ++ left = opts->latest_time + opts->root_unlock_time - opts->now; ++ } ++ ++ if (left > 0) { ++ left = (left + 59)/60; /* minutes */ ++ ++ pam_info(pamh, _("Account temporarily locked due to %d failed logins"), ++ opts->failures); ++ pam_info(pamh, _("(%d minutes left to unlock)"), (int)left); ++ } ++ else { ++ pam_info(pamh, _("Account locked due to %d failed logins"), ++ opts->failures); ++ } ++ } ++} ++ ++static void ++tally_cleanup(struct tally_data *tallies, int fd) ++{ ++ if (fd != -1) { ++ close(fd); ++ } ++ ++ free(tallies->records); ++} ++ ++/*---------------------------------------------------------------------*/ ++ ++PAM_EXTERN int ++pam_sm_authenticate(pam_handle_t *pamh, int flags, ++ int argc, const char **argv) ++{ ++ struct options opts; ++ int rv, fd = -1; ++ struct tally_data tallies; ++ ++ memset(&tallies, 0, sizeof(tallies)); ++ ++ args_parse(pamh, argc, argv, flags, &opts); ++ ++ pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ ++ ++ if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { ++ return rv; ++ } ++ ++ switch (opts.action) { ++ case FAILLOCK_ACTION_PREAUTH: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_AUTH_ERR && !(opts.flags & FAILLOCK_FLAG_SILENT)) { ++ faillock_message(pamh, &opts); ++ } ++ break; ++ ++ case FAILLOCK_ACTION_AUTHSUCC: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_SUCCESS) { ++ reset_tally(pamh, &opts, &fd); ++ } ++ break; ++ ++ case FAILLOCK_ACTION_AUTHFAIL: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_SUCCESS) { ++ rv = PAM_IGNORE; /* this return value should be ignored */ ++ write_tally(pamh, &opts, &tallies, &fd); ++ } ++ break; ++ } ++ ++ tally_cleanup(&tallies, fd); ++ ++ return rv; ++} ++ ++/*---------------------------------------------------------------------*/ ++ ++PAM_EXTERN int ++pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED, ++ int argc UNUSED, const char **argv UNUSED) ++{ ++ return PAM_SUCCESS; ++} ++ ++/*---------------------------------------------------------------------*/ ++ ++PAM_EXTERN int ++pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, ++ int argc, const char **argv) ++{ ++ struct options opts; ++ int rv, fd = -1; ++ struct tally_data tallies; ++ ++ memset(&tallies, 0, sizeof(tallies)); ++ ++ args_parse(pamh, argc, argv, flags, &opts); ++ ++ opts.action = FAILLOCK_ACTION_AUTHSUCC; ++ ++ if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { ++ return rv; ++ } ++ ++ check_tally(pamh, &opts, &tallies, &fd); /* for auditing */ ++ reset_tally(pamh, &opts, &fd); ++ ++ tally_cleanup(&tallies, fd); ++ ++ return PAM_SUCCESS; ++} ++ ++/*-----------------------------------------------------------------------*/ ++ ++#ifdef PAM_STATIC ++ ++/* static module data */ ++ ++struct pam_module _pam_faillock_modstruct = { ++ MODULE_NAME, ++#ifdef PAM_SM_AUTH ++ pam_sm_authenticate, ++ pam_sm_setcred, ++#else ++ NULL, ++ NULL, ++#endif ++#ifdef PAM_SM_ACCOUNT ++ pam_sm_acct_mgmt, ++#else ++ NULL, ++#endif ++ NULL, ++ NULL, ++ NULL, ++}; ++ ++#endif /* #ifdef PAM_STATIC */ ++ +diff -up Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.8.xml.faillock Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.8.xml +--- Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.8.xml.faillock 2016-04-04 16:37:38.696260359 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/pam_faillock.8.xml 2016-04-28 17:09:04.679596165 +0200 +@@ -0,0 +1,408 @@ ++ ++ ++ ++ ++ ++ ++ pam_faillock ++ 8 ++ Linux-PAM Manual ++ ++ ++ ++ pam_faillock ++ Module counting authentication failures during a specified interval ++ ++ ++ ++ ++ auth ... pam_faillock.so ++ ++ preauth|authfail|authsucc ++ ++ ++ dir=/path/to/tally-directory ++ ++ ++ even_deny_root ++ ++ ++ deny=n ++ ++ ++ fail_interval=n ++ ++ ++ unlock_time=n ++ ++ ++ root_unlock_time=n ++ ++ ++ audit ++ ++ ++ silent ++ ++ ++ no_log_info ++ ++ ++ ++ account ... pam_faillock.so ++ ++ dir=/path/to/tally-directory ++ ++ ++ no_log_info ++ ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ ++ This module maintains a list of failed authentication attempts per ++ user during a specified interval and locks the account in case ++ there were more than deny consecutive ++ failed authentications. ++ ++ ++ Normally, failed attempts to authenticate root will ++ not cause the root account to become ++ blocked, to prevent denial-of-service: if your users aren't given ++ shell accounts and root may only login via su or ++ at the machine console (not telnet/rsh, etc), this is safe. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ This argument must be set accordingly to the position of this module ++ instance in the PAM stack. ++ ++ ++ The preauth argument must be used when the module ++ is called before the modules which ask for the user credentials such ++ as the password. The module just examines whether the user should ++ be blocked from accessing the service in case there were anomalous ++ number of failed consecutive authentication attempts recently. This ++ call is optional if authsucc is used. ++ ++ ++ The authfail argument must be used when the module ++ is called after the modules which determine the authentication outcome, ++ failed. Unless the user is already blocked due to previous authentication ++ failures, the module will record the failure into the appropriate user ++ tally file. ++ ++ ++ The authsucc argument must be used when the module ++ is called after the modules which determine the authentication outcome, ++ succeded. Unless the user is already blocked due to previous authentication ++ failures, the module will then clear the record of the failures in the ++ respective user tally file. Otherwise it will return authentication error. ++ If this call is not done, the pam_faillock will not distinguish between ++ consecutive and non-consecutive failed authentication attempts. The ++ preauth call must be used in such case. Due to ++ complications in the way the PAM stack can be configured it is also ++ possible to call pam_faillock as an account module. ++ In such configuration the module must be also called in the ++ preauth stage. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The directory where the user files with the failure records are kept. The ++ default is /var/run/faillock. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Will log the user name into the system log if the user is not found. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't print informative messages. This option is implicite ++ in the authfail and authsucc ++ functions. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't log informative messages via syslog3. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Deny access if the number of consecutive authentication failures ++ for this user during the recent interval exceeds ++ n. The default is 3. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The length of the interval during which the consecutive ++ authentication failures must happen for the user account ++ lock out is n seconds. ++ The default is 900 (15 minutes). ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The access will be reenabled after ++ n seconds after the lock out. ++ The value 0 has the same meaning as value ++ never - the access ++ will not be reenabled without resetting the faillock ++ entries by the faillock8 command. ++ The default is 600 (10 minutes). ++ ++ ++ Note that the default directory that pam_faillock ++ uses is usually cleared on system boot so the access will be also reenabled ++ after system reboot. If that is undesirable a different tally directory ++ must be set with the option. ++ ++ ++ Also note that it is usually undesirable to permanently lock ++ out the users as they can become easily a target of denial of service ++ attack unless the usernames are random and kept secret to potential ++ attackers. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Root account can become locked as well as regular accounts. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This option implies option. ++ Allow access after n seconds ++ to root account after the account is locked. In case the ++ option is not specified the value is the same as of the ++ option. ++ ++ ++ ++ ++ ++ ++ ++ MODULE TYPES PROVIDED ++ ++ The and module types are ++ provided. ++ ++ ++ ++ ++ RETURN VALUES ++ ++ ++ PAM_AUTH_ERR ++ ++ ++ A invalid option was given, the module was not able ++ to retrieve the user name, no valid counter file ++ was found, or too many failed logins. ++ ++ ++ ++ ++ PAM_SUCCESS ++ ++ ++ Everything was successful. ++ ++ ++ ++ ++ PAM_IGNORE ++ ++ ++ User not present in passwd database. ++ ++ ++ ++ ++ ++ ++ ++ NOTES ++ ++ pam_faillock setup in the PAM stack is different ++ from the pam_tally2 module setup. ++ ++ ++ The individual files with the failure records are created as owned by ++ the user. This allows pam_faillock.so module ++ to work correctly when it is called from a screensaver. ++ ++ ++ Note that using the module in without the ++ option or with requisite ++ control field leaks an information about existence or ++ non-existence of an user account in the system because ++ the failures are not recorded for the unknown users. The message ++ about the user account being locked is never displayed for nonexisting ++ user accounts allowing the adversary to infer that a particular account ++ is not existing on a system. ++ ++ ++ ++ ++ EXAMPLES ++ ++ Here are two possible configuration examples for /etc/pam.d/login. ++ They make pam_faillock to lock the account after 4 consecutive ++ failed logins during the default interval of 15 minutes. Root account will be locked ++ as well. The accounts will be automatically unlocked after 20 minutes. ++ ++ ++ In the first example the module is called only in the auth ++ phase and the module does not print any information about the account blocking ++ by pam_faillock. The preauth call can ++ be added to tell the user that his login is blocked by the module and also to abort ++ the authentication without even asking for password in such case. ++ ++ ++auth required pam_securetty.so ++auth required pam_env.so ++auth required pam_nologin.so ++# optionally call: auth requisite pam_faillock.so preauth deny=4 even_deny_root unlock_time=1200 ++# to display the message about account being locked ++auth [success=1 default=bad] pam_unix.so ++auth [default=die] pam_faillock.so authfail deny=4 even_deny_root unlock_time=1200 ++auth sufficient pam_faillock.so authsucc deny=4 even_deny_root unlock_time=1200 ++auth required pam_deny.so ++account required pam_unix.so ++password required pam_unix.so shadow ++session required pam_selinux.so close ++session required pam_loginuid.so ++session required pam_unix.so ++session required pam_selinux.so open ++ ++ ++ In the second example the module is called both in the auth ++ and account phases and the module gives the authenticating ++ user message when the account is locked ++ ++ ++auth required pam_securetty.so ++auth required pam_env.so ++auth required pam_nologin.so ++auth required pam_faillock.so preauth silent deny=4 even_deny_root unlock_time=1200 ++# optionally use requisite above if you do not want to prompt for the password ++# on locked accounts, possibly with removing the silent option as well ++auth sufficient pam_unix.so ++auth [default=die] pam_faillock.so authfail deny=4 even_deny_root unlock_time=1200 ++auth required pam_deny.so ++account required pam_faillock.so ++# if you drop the above call to pam_faillock.so the lock will be done also ++# on non-consecutive authentication failures ++account required pam_unix.so ++password required pam_unix.so shadow ++session required pam_selinux.so close ++session required pam_loginuid.so ++session required pam_unix.so ++session required pam_selinux.so open ++ ++ ++ ++ ++ FILES ++ ++ ++ /var/run/faillock/* ++ ++ the files logging the authentication failures for users ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ faillock8 ++ , ++ ++ pam.conf5 ++ , ++ ++ pam.d5 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ pam_faillock was written by Tomas Mraz. ++ ++ ++ ++ +diff -up Linux-PAM-1.2.1/modules/pam_faillock/README.xml.faillock Linux-PAM-1.2.1/modules/pam_faillock/README.xml +--- Linux-PAM-1.2.1/modules/pam_faillock/README.xml.faillock 2015-06-25 10:42:21.483374875 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/README.xml 2015-06-25 10:42:21.483374875 +0200 +@@ -0,0 +1,46 @@ ++ ++ ++--> ++]> ++ ++
++ ++ ++ ++ ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="pam_faillock.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_faillock-name"]/*)'/> ++ ++ ++ ++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
+diff -up Linux-PAM-1.2.1/modules/pam_faillock/tst-pam_faillock.faillock Linux-PAM-1.2.1/modules/pam_faillock/tst-pam_faillock +--- Linux-PAM-1.2.1/modules/pam_faillock/tst-pam_faillock.faillock 2015-06-25 10:42:21.483374875 +0200 ++++ Linux-PAM-1.2.1/modules/pam_faillock/tst-pam_faillock 2015-06-25 10:42:21.483374875 +0200 +@@ -0,0 +1,2 @@ ++#!/bin/sh ++../../tests/tst-dlopen .libs/pam_faillock.so diff --git a/SOURCES/pam-1.3.0-pwhistory-helper.patch b/SOURCES/pam-1.3.0-pwhistory-helper.patch new file mode 100644 index 0000000..554e5c8 --- /dev/null +++ b/SOURCES/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 ++# 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 ++ * 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 ++#include + #include + #include + #include +@@ -47,6 +49,7 @@ + #include + #include + #include ++#include + #include + + #if defined (HAVE_XCRYPT_H) +@@ -55,7 +58,14 @@ + #include + #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 + #include ++#endif + #include + + #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 ++ * 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 ++#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 ++ * 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 + #include + #include +-#include + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + + #include + #include +@@ -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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 @@ ++ ++ ++ ++ ++ ++ ++ pwhistory_helper ++ 8 ++ Linux-PAM Manual ++ ++ ++ ++ pwhistory_helper ++ Helper binary that transfers password hashes from passwd or shadow to opasswd ++ ++ ++ ++ ++ pwhistory_helper ++ ++ ... ++ ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ ++ pwhistory_helper is a helper program for the ++ pam_pwhistory 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. ++ ++ ++ ++ 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. ++ ++ ++ ++ The interface of the helper - command line options, and input/output ++ data format are internal to the pam_pwhistory ++ module and it should not be called directly from applications. ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ pam_pwhistory8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ Written by Tomas Mraz based on the code originally in ++ pam_pwhistory and pam_unix modules. ++ ++ ++ ++ diff --git a/SOURCES/pam-1.3.0-unix-nomsg.patch b/SOURCES/pam-1.3.0-unix-nomsg.patch new file mode 100644 index 0000000..33c2267 --- /dev/null +++ b/SOURCES/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/SOURCES/pam-1.3.1-access-handle-hostnames.patch b/SOURCES/pam-1.3.1-access-handle-hostnames.patch new file mode 100644 index 0000000..b73ba8a --- /dev/null +++ b/SOURCES/pam-1.3.1-access-handle-hostnames.patch @@ -0,0 +1,158 @@ +diff -up Linux-PAM-1.3.1/modules/pam_access/pam_access.c.access-handle-hostnames Linux-PAM-1.3.1/modules/pam_access/pam_access.c +--- Linux-PAM-1.3.1/modules/pam_access/pam_access.c.access-handle-hostnames 2024-01-19 16:45:18.319862531 +0100 ++++ Linux-PAM-1.3.1/modules/pam_access/pam_access.c 2024-01-19 16:50:34.239545948 +0100 +@@ -683,7 +683,7 @@ string_match (pam_handle_t *pamh, const + /* + * If the token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the string. +- * "NONE" token matches NULL string. ++ * "NONE" token matches NULL string. + */ + + if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ +@@ -701,7 +701,8 @@ string_match (pam_handle_t *pamh, const + + /* network_netmask_match - match a string against one token + * where string is a hostname or ip (v4,v6) address and tok +- * represents either a single ip (v4,v6) address or a network/netmask ++ * represents either a hostname, a single ip (v4,v6) address ++ * or a network/netmask + */ + static int + network_netmask_match (pam_handle_t *pamh, +@@ -710,10 +711,12 @@ network_netmask_match (pam_handle_t *pam + char *netmask_ptr; + char netmask_string[MAXHOSTNAMELEN + 1]; + int addr_type; ++ struct addrinfo *ai = NULL; + + if (item->debug) +- pam_syslog (pamh, LOG_DEBUG, ++ pam_syslog (pamh, LOG_DEBUG, + "network_netmask_match: tok=%s, item=%s", tok, string); ++ + /* OK, check if tok is of type addr/mask */ + if ((netmask_ptr = strchr(tok, '/')) != NULL) + { +@@ -745,52 +748,109 @@ network_netmask_match (pam_handle_t *pam + netmask_ptr = number_to_netmask(netmask, addr_type, + netmask_string, MAXHOSTNAMELEN); + } +- } ++ ++ /* ++ * Construct an addrinfo list from the IP address. ++ * This should not fail as the input is a correct IP address... ++ */ ++ if (getaddrinfo (tok, NULL, NULL, &ai) != 0) ++ { ++ return NO; ++ } ++ } + else +- /* NO, then check if it is only an addr */ +- if (isipaddr(tok, NULL, NULL) != YES) ++ { ++ /* ++ * It is either an IP address or a hostname. ++ * Let getaddrinfo sort everything out ++ */ ++ if (getaddrinfo (tok, NULL, NULL, &ai) != 0) + { ++ if (item->debug) ++ pam_syslog(pamh, LOG_DEBUG, "cannot resolve hostname \"%s\"", tok); ++ + return NO; + } ++ netmask_ptr = NULL; ++ } + + if (isipaddr(string, NULL, NULL) != YES) + { +- /* Assume network/netmask with a name of a host. */ + struct addrinfo hint; + ++ /* Assume network/netmask with a name of a host. */ + memset (&hint, '\0', sizeof (hint)); + hint.ai_flags = AI_CANONNAME; + hint.ai_family = AF_UNSPEC; + + if (item->gai_rv != 0) ++ { ++ freeaddrinfo(ai); + return NO; ++ } + else if (!item->res && + (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0) ++ { ++ freeaddrinfo(ai); + return NO; ++ } + else + { + struct addrinfo *runp = item->res; ++ struct addrinfo *runp1; + + while (runp != NULL) + { + char buf[INET6_ADDRSTRLEN]; + +- inet_ntop (runp->ai_family, +- runp->ai_family == AF_INET +- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr +- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, +- buf, sizeof (buf)); ++ if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0) ++ { ++ freeaddrinfo(ai); ++ return NO; ++ } + +- if (are_addresses_equal(buf, tok, netmask_ptr)) ++ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) + { +- return YES; ++ char buf1[INET6_ADDRSTRLEN]; ++ ++ if (runp->ai_family != runp1->ai_family) ++ continue; ++ ++ if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0) ++ { ++ freeaddrinfo(ai); ++ return NO; ++ } ++ ++ if (are_addresses_equal (buf, buf1, netmask_ptr)) ++ { ++ freeaddrinfo(ai); ++ return YES; ++ } + } + runp = runp->ai_next; + } + } + } + else +- return (are_addresses_equal(string, tok, netmask_ptr)); ++ { ++ struct addrinfo *runp1; ++ ++ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) ++ { ++ char buf1[INET6_ADDRSTRLEN]; ++ ++ (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST); ++ ++ if (are_addresses_equal(string, buf1, netmask_ptr)) ++ { ++ freeaddrinfo(ai); ++ return YES; ++ } ++ } ++ } ++ ++ freeaddrinfo(ai); + + return NO; + } diff --git a/SOURCES/pam-1.3.1-audit-error.patch b/SOURCES/pam-1.3.1-audit-error.patch new file mode 100644 index 0000000..f01172b --- /dev/null +++ b/SOURCES/pam-1.3.1-audit-error.patch @@ -0,0 +1,35 @@ +From b429ea18b1c9c8953df5169c6a453b4255a6f23d Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 27 Feb 2020 11:48:47 +0100 +Subject: [PATCH] pam_tty_audit: if kernel audit is disabled return PAM_IGNORE + +If kernel audit is disabled the socket open will return +EPROTONOSUPPORT. +Return PAM_IGNORE from pam_tty_audit and log a warning +in this situation so login is not blocked by the module. +--- + modules/pam_tty_audit/pam_tty_audit.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c +index 7dbcada2..589c60a2 100644 +--- a/modules/pam_tty_audit/pam_tty_audit.c ++++ b/modules/pam_tty_audit/pam_tty_audit.c +@@ -351,6 +351,14 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) + + fd = nl_open (); + if (fd == -1 ++ && errno == EPROTONOSUPPORT) ++ { ++ pam_syslog (pamh, LOG_WARNING, "unable to open audit socket, audit not " ++ "supported; tty_audit skipped"); ++ free (old_status); ++ return PAM_IGNORE; ++ } ++ else if (fd == -1 + || nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0 + || nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0) + { +-- +2.25.2 + diff --git a/SOURCES/pam-1.3.1-authtok-verify-fix.patch b/SOURCES/pam-1.3.1-authtok-verify-fix.patch new file mode 100644 index 0000000..6c40cdc --- /dev/null +++ b/SOURCES/pam-1.3.1-authtok-verify-fix.patch @@ -0,0 +1,88 @@ +From 27d04a849fd9f9cfd4b35eb80d687817830183df Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Wed, 7 Aug 2019 12:22:55 +0200 +Subject: [PATCH] pam_get_authtok_verify: Avoid duplicate password verification + +If password was already verified by previous modules in the stack +it does not need to be verified by pam_get_authtok_verify either. + +* libpam/pam_get_authtok.c (pam_get_authtok_internal): Set the authtok_verified + appropriately. + (pam_get_authtok_verify): Do not prompt if authtok_verified is set and + set it when the password is verified. +* libpam/pam_private.h: Add authtok_verified to the pam handle struct. +* libpam/pam_start.c (pam_start): Initialize authtok_verified. +--- + libpam/pam_get_authtok.c | 10 ++++++++++ + libpam/pam_private.h | 1 + + libpam/pam_start.c | 1 + + 3 files changed, 12 insertions(+) + +diff --git a/libpam/pam_get_authtok.c b/libpam/pam_get_authtok.c +index 800c6e5..99eb25f 100644 +--- a/libpam/pam_get_authtok.c ++++ b/libpam/pam_get_authtok.c +@@ -140,6 +140,8 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item, + } + else if (chpass) + { ++ pamh->authtok_verified = 0; ++ + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], + PROMPT1, authtok_type, + strlen (authtok_type) > 0?" ":""); +@@ -184,6 +186,9 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item, + if (retval != PAM_SUCCESS) + return retval; + ++ if (chpass > 1) ++ pamh->authtok_verified = 1; ++ + return pam_get_item(pamh, item, (const void **)authtok); + } + +@@ -214,6 +219,9 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok, + if (authtok == NULL || pamh->choice != PAM_CHAUTHTOK) + return PAM_SYSTEM_ERR; + ++ if (pamh->authtok_verified) ++ return pam_get_item (pamh, PAM_AUTHTOK, (const void **)authtok); ++ + if (prompt != NULL) + { + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp, +@@ -252,5 +260,7 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok, + if (retval != PAM_SUCCESS) + return retval; + ++ pamh->authtok_verified = 1; ++ + return pam_get_item(pamh, PAM_AUTHTOK, (const void **)authtok); + } +diff --git a/libpam/pam_private.h b/libpam/pam_private.h +index 7ff9f75..58a26f5 100644 +--- a/libpam/pam_private.h ++++ b/libpam/pam_private.h +@@ -172,6 +172,7 @@ struct pam_handle { + #ifdef HAVE_LIBAUDIT + int audit_state; /* keep track of reported audit messages */ + #endif ++ int authtok_verified; + }; + + /* Values for select arg to _pam_dispatch() */ +diff --git a/libpam/pam_start.c b/libpam/pam_start.c +index 328416d..e27c64b 100644 +--- a/libpam/pam_start.c ++++ b/libpam/pam_start.c +@@ -94,6 +94,7 @@ int pam_start ( + #endif + (*pamh)->xdisplay = NULL; + (*pamh)->authtok_type = NULL; ++ (*pamh)->authtok_verified = 0; + memset (&((*pamh)->xauth), 0, sizeof ((*pamh)->xauth)); + + if (((*pamh)->pam_conversation = (struct pam_conv *) +-- +2.20.1 + diff --git a/SOURCES/pam-1.3.1-console-build.patch b/SOURCES/pam-1.3.1-console-build.patch new file mode 100644 index 0000000..b9338cd --- /dev/null +++ b/SOURCES/pam-1.3.1-console-build.patch @@ -0,0 +1,11 @@ +diff -up Linux-PAM-1.3.1/modules/pam_console/sed-static.console-build Linux-PAM-1.3.1/modules/pam_console/sed-static +--- Linux-PAM-1.3.1/modules/pam_console/sed-static.console-build 2014-01-31 14:17:53.000000000 +0100 ++++ Linux-PAM-1.3.1/modules/pam_console/sed-static 2018-09-10 15:06:04.115302315 +0200 +@@ -13,6 +13,7 @@ sed ' + /^YY_BUFFER_STATE yy_scan_buffer/s/^/STATIC / + /^YY_BUFFER_STATE yy_scan_string/s/^/STATIC / + /^void yy_switch_to_buffer/s/^/STATIC / ++/^extern int yylex/s/^extern /STATIC / + /define YY_DECL int yylex/s/YY_DECL /YY_DECL STATIC / + /^int yyparse/s/^/STATIC / + /^void yyrestart/s/^/STATIC / diff --git a/SOURCES/pam-1.3.1-coverity.patch b/SOURCES/pam-1.3.1-coverity.patch new file mode 100644 index 0000000..cecf768 --- /dev/null +++ b/SOURCES/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/SOURCES/pam-1.3.1-faillock-create-tallydir.patch b/SOURCES/pam-1.3.1-faillock-create-tallydir.patch new file mode 100644 index 0000000..e2d2caf --- /dev/null +++ b/SOURCES/pam-1.3.1-faillock-create-tallydir.patch @@ -0,0 +1,13 @@ +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-create-tallydir Linux-PAM-1.3.1/modules/pam_faillock/faillock.c +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-create-tallydir 2024-01-08 11:32:02.122392119 +0100 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.c 2024-01-08 11:33:10.916515943 +0100 +@@ -74,6 +74,9 @@ open_tally (const char *dir, const char + + if (create) { + flags |= O_CREAT; ++ if (access(dir, F_OK) != 0) { ++ mkdir(dir, 0755); ++ } + } + + fd = open(path, flags, 0600); diff --git a/SOURCES/pam-1.3.1-faillock-load-conf-from-file.patch b/SOURCES/pam-1.3.1-faillock-load-conf-from-file.patch new file mode 100644 index 0000000..81ea7cc --- /dev/null +++ b/SOURCES/pam-1.3.1-faillock-load-conf-from-file.patch @@ -0,0 +1,1212 @@ +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file 2022-05-26 10:57:11.713067506 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml 2022-05-26 10:57:11.747067749 +0200 +@@ -57,12 +57,29 @@ + + + ++ ++ ++ ++ ++ The file where the configuration is located. The default is ++ /etc/security/faillock.conf. ++ ++ ++ ++ ++ + + + + +- The directory where the user files with the failure records are kept. The +- default is /var/run/faillock. ++ The directory where the user files with the failure records are kept. ++ ++ ++ The priority to set this option is to use the value provided ++ from the command line. If this isn't provided, then the value ++ from the configuration file is used. Finally, if neither of ++ them has been provided, then ++ /var/run/faillock is used. + + + +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file 2022-05-26 10:57:11.747067749 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c 2022-05-26 10:57:11.747067749 +0200 +@@ -0,0 +1,266 @@ ++/* ++ * Copyright (c) 2022 Tomas Mraz ++ * Copyright (c) 2022 Iker Pedrosa ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "faillock_config.h" ++#include "faillock.h" ++ ++#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" ++#ifdef VENDOR_SCONFIGDIR ++#define VENDOR_FAILLOCK_DEFAULT_CONF VENDOR_SCONFIGDIR "/faillock.conf" ++#endif ++ ++static void PAM_FORMAT((printf, 3, 4)) PAM_NONNULL((3)) ++config_log(const pam_handle_t *pamh, int priority, const char *fmt, ...) ++{ ++ va_list args; ++ ++ va_start(args, fmt); ++ if (pamh) { ++ pam_vsyslog(pamh, priority, fmt, args); ++ } else { ++ char *buf = NULL; ++ ++ if (vasprintf(&buf, fmt, args) < 0) { ++ fprintf(stderr, "vasprintf: %m"); ++ va_end(args); ++ return; ++ } ++ fprintf(stderr, "%s\n", buf); ++ free(buf); ++ } ++ va_end(args); ++} ++ ++/* parse a single configuration file */ ++int ++read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) ++{ ++ char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; ++ const char *fname = (cfgfile != NULL) ? cfgfile : FAILLOCK_DEFAULT_CONF; ++ FILE *f = fopen(fname, "r"); ++ ++#ifdef VENDOR_FAILLOCK_DEFAULT_CONF ++ if (f == NULL && errno == ENOENT && cfgfile == NULL) { ++ /* ++ * If the default configuration file in /etc does not exist, ++ * try the vendor configuration file as fallback. ++ */ ++ f = fopen(VENDOR_FAILLOCK_DEFAULT_CONF, "r"); ++ } ++#endif /* VENDOR_FAILLOCK_DEFAULT_CONF */ ++ ++ if (f == NULL) { ++ /* ignore non-existent default config file */ ++ if (errno == ENOENT && cfgfile == NULL) ++ return PAM_SUCCESS; ++ return PAM_SERVICE_ERR; ++ } ++ ++ while (fgets(linebuf, sizeof(linebuf), f) != NULL) { ++ size_t len; ++ char *ptr; ++ char *name; ++ int eq; ++ ++ len = strlen(linebuf); ++ /* len cannot be 0 unless there is a bug in fgets */ ++ if (len && linebuf[len - 1] != '\n' && !feof(f)) { ++ (void) fclose(f); ++ return PAM_SERVICE_ERR; ++ } ++ ++ if ((ptr=strchr(linebuf, '#')) != NULL) { ++ *ptr = '\0'; ++ } else { ++ ptr = linebuf + len; ++ } ++ ++ /* drop terminating whitespace including the \n */ ++ while (ptr > linebuf) { ++ if (!isspace(*(ptr-1))) { ++ *ptr = '\0'; ++ break; ++ } ++ --ptr; ++ } ++ ++ /* skip initial whitespace */ ++ for (ptr = linebuf; isspace(*ptr); ptr++); ++ if (*ptr == '\0') ++ continue; ++ ++ /* grab the key name */ ++ eq = 0; ++ name = ptr; ++ while (*ptr != '\0') { ++ if (isspace(*ptr) || *ptr == '=') { ++ eq = *ptr == '='; ++ *ptr = '\0'; ++ ++ptr; ++ break; ++ } ++ ++ptr; ++ } ++ ++ /* grab the key value */ ++ while (*ptr != '\0') { ++ if (*ptr != '=' || eq) { ++ if (!isspace(*ptr)) { ++ break; ++ } ++ } else { ++ eq = 1; ++ } ++ ++ptr; ++ } ++ ++ /* set the key:value pair on opts */ ++ set_conf_opt(pamh, opts, name, ptr); ++ } ++ ++ (void)fclose(f); ++ return PAM_SUCCESS; ++} ++ ++void ++set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, ++ const char *value) ++{ ++ if (strcmp(name, "dir") == 0) { ++ if (value[0] != '/') { ++ config_log(pamh, LOG_ERR, ++ "Tally directory is not absolute path (%s); keeping value", ++ value); ++ } else { ++ free(opts->dir); ++ opts->dir = strdup(value); ++ if (opts->dir == NULL) { ++ opts->fatal_error = 1; ++ config_log(pamh, LOG_CRIT, "Error allocating memory: %m"); ++ } ++ } ++ } ++ else if (strcmp(name, "deny") == 0) { ++ if (sscanf(value, "%hu", &opts->deny) != 1) { ++ config_log(pamh, LOG_ERR, ++ "Bad number supplied for deny argument"); ++ } ++ } ++ else if (strcmp(name, "fail_interval") == 0) { ++ unsigned int temp; ++ if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ config_log(pamh, LOG_ERR, ++ "Bad number supplied for fail_interval argument"); ++ } else { ++ opts->fail_interval = temp; ++ } ++ } ++ else if (strcmp(name, "unlock_time") == 0) { ++ unsigned int temp; ++ ++ if (strcmp(value, "never") == 0) { ++ opts->unlock_time = 0; ++ } ++ else if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ config_log(pamh, LOG_ERR, ++ "Bad number supplied for unlock_time argument"); ++ } ++ else { ++ opts->unlock_time = temp; ++ } ++ } ++ else if (strcmp(name, "root_unlock_time") == 0) { ++ unsigned int temp; ++ ++ if (strcmp(value, "never") == 0) { ++ opts->root_unlock_time = 0; ++ } ++ else if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ config_log(pamh, LOG_ERR, ++ "Bad number supplied for root_unlock_time argument"); ++ } else { ++ opts->root_unlock_time = temp; ++ } ++ } ++ else if (strcmp(name, "admin_group") == 0) { ++ free(opts->admin_group); ++ opts->admin_group = strdup(value); ++ if (opts->admin_group == NULL) { ++ opts->fatal_error = 1; ++ config_log(pamh, LOG_CRIT, "Error allocating memory: %m"); ++ } ++ } ++ else if (strcmp(name, "even_deny_root") == 0) { ++ opts->flags |= FAILLOCK_FLAG_DENY_ROOT; ++ } ++ else if (strcmp(name, "audit") == 0) { ++ opts->flags |= FAILLOCK_FLAG_AUDIT; ++ } ++ else if (strcmp(name, "silent") == 0) { ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++ } ++ else if (strcmp(name, "no_log_info") == 0) { ++ opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; ++ } ++ else if (strcmp(name, "local_users_only") == 0) { ++ opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; ++ } ++ else if (strcmp(name, "nodelay") == 0) { ++ opts->flags |= FAILLOCK_FLAG_NO_DELAY; ++ } ++ else { ++ config_log(pamh, LOG_ERR, "Unknown option: %s", name); ++ } ++} ++ ++const char *get_tally_dir(const struct options *opts) ++{ ++ return (opts->dir != NULL) ? opts->dir : FAILLOCK_DEFAULT_TALLYDIR; ++} +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file 2022-05-26 10:57:11.747067749 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h 2022-05-26 10:57:11.747067749 +0200 +@@ -0,0 +1,89 @@ ++/* ++ * Copyright (c) 2022 Tomas Mraz ++ * Copyright (c) 2022 Iker Pedrosa ++ * ++ * 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. ++ */ ++ ++/* ++ * faillock_config.h - load configuration options from file ++ * ++ */ ++ ++#ifndef _FAILLOCK_CONFIG_H ++#define _FAILLOCK_CONFIG_H ++ ++#include ++#include ++#include ++ ++#include ++ ++#define FAILLOCK_FLAG_DENY_ROOT 0x1 ++#define FAILLOCK_FLAG_AUDIT 0x2 ++#define FAILLOCK_FLAG_SILENT 0x4 ++#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 ++#define FAILLOCK_FLAG_UNLOCKED 0x10 ++#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 ++#define FAILLOCK_FLAG_NO_DELAY 0x40 ++ ++#define FAILLOCK_CONF_MAX_LINELEN 1023 ++#define MAX_TIME_INTERVAL 604800 /* 7 days */ ++ ++struct options { ++ unsigned int action; ++ unsigned int flags; ++ unsigned short deny; ++ unsigned int fail_interval; ++ unsigned int unlock_time; ++ unsigned int root_unlock_time; ++ char *dir; ++ const char *user; ++ char *admin_group; ++ int failures; ++ uint64_t latest_time; ++ uid_t uid; ++ int is_admin; ++ uint64_t now; ++ int fatal_error; ++ ++ unsigned int reset; ++ const char *progname; ++}; ++ ++int read_config_file(pam_handle_t *pamh, struct options *opts, ++ const char *cfgfile); ++void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, ++ const char *value); ++const char *get_tally_dir(const struct options *opts); ++ ++#endif /* _FAILLOCK_CONFIG_H */ +diff -up Linux-PAM-1.3.1/modules/pam_faillock/main.c.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/main.c +--- Linux-PAM-1.3.1/modules/pam_faillock/main.c.faillock-load-conf-from-file 2022-05-26 10:57:11.713067506 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/main.c 2022-05-26 10:57:11.747067749 +0200 +@@ -48,43 +48,50 @@ + #include + #endif + ++#include "pam_inline.h" + #include "faillock.h" +- +-struct options { +- unsigned int reset; +- const char *dir; +- const char *user; +- const char *progname; +-}; ++#include "faillock_config.h" + + static int + args_parse(int argc, char **argv, struct options *opts) + { + int i; ++ int rv; ++ const char *dir = NULL; ++ const char *conf = NULL; ++ + memset(opts, 0, sizeof(*opts)); + +- opts->dir = FAILLOCK_DEFAULT_TALLYDIR; + opts->progname = argv[0]; + + for (i = 1; i < argc; ++i) { +- +- if (strcmp(argv[i], "--dir") == 0) { ++ if (strcmp(argv[i], "--conf") == 0) { ++ ++i; ++ if (i >= argc || strlen(argv[i]) == 0) { ++ fprintf(stderr, "%s: No configuration file supplied.\n", ++ argv[0]); ++ return -1; ++ } ++ conf = argv[i]; ++ } ++ else if (strcmp(argv[i], "--dir") == 0) { + ++i; + if (i >= argc || strlen(argv[i]) == 0) { +- fprintf(stderr, "%s: No directory supplied.\n", argv[0]); ++ fprintf(stderr, "%s: No records directory supplied.\n", ++ argv[0]); + return -1; + } +- opts->dir = argv[i]; +- } ++ dir = argv[i]; ++ } + else if (strcmp(argv[i], "--user") == 0) { + ++i; + if (i >= argc || strlen(argv[i]) == 0) { +- fprintf(stderr, "%s: No user name supplied.\n", argv[0]); ++ fprintf(stderr, "%s: No user name supplied.\n", argv[0]); + return -1; + } +- opts->user = argv[i]; ++ opts->user = argv[i]; + } +- else if (strcmp(argv[i], "--reset") == 0) { ++ else if (strcmp(argv[i], "--reset") == 0) { + opts->reset = 1; + } + else { +@@ -92,6 +99,21 @@ args_parse(int argc, char **argv, struct + return -1; + } + } ++ ++ if ((rv = read_config_file(NULL, opts, conf)) != PAM_SUCCESS) { ++ fprintf(stderr, "Configuration file missing or broken"); ++ return rv; ++ } ++ ++ if (dir != NULL) { ++ free(opts->dir); ++ opts->dir = strdup(dir); ++ if (opts->dir == NULL) { ++ fprintf(stderr, "Error allocating memory: %m"); ++ return -1; ++ } ++ } ++ + return 0; + } + +@@ -109,10 +131,11 @@ do_user(struct options *opts, const char + int rv; + struct tally_data tallies; + struct passwd *pwd; ++ const char *dir = get_tally_dir(opts); + + pwd = getpwnam(user); + +- fd = open_tally(opts->dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); ++ fd = open_tally(dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); + + if (fd == -1) { + if (errno == ENOENT) { +@@ -189,11 +212,11 @@ do_allusers(struct options *opts) + { + struct dirent **userlist; + int rv, i; ++ const char *dir = get_tally_dir(opts); + +- rv = scandir(opts->dir, &userlist, NULL, alphasort); ++ rv = scandir(dir, &userlist, NULL, alphasort); + if (rv < 0) { +- fprintf(stderr, "%s: Error reading tally directory: ", opts->progname); +- perror(NULL); ++ fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname); + return 2; + } + +diff -up Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am +--- Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file 2022-05-26 10:57:11.727067606 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am 2022-05-26 10:57:59.032406450 +0200 +@@ -17,7 +17,7 @@ TESTS = tst-pam_faillock + securelibdir = $(SECUREDIR) + secureconfdir = $(SCONFIGDIR) + +-noinst_HEADERS = faillock.h ++noinst_HEADERS = faillock.h faillock_config.h + + faillock_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include @PIE_CFLAGS@ + pam_faillock_la_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include +@@ -36,8 +36,8 @@ secureconf_DATA = faillock.conf + securelib_LTLIBRARIES = pam_faillock.la + sbin_PROGRAMS = faillock + +-pam_faillock_la_SOURCES = pam_faillock.c faillock.c +-faillock_SOURCES = main.c faillock.c ++pam_faillock_la_SOURCES = pam_faillock.c faillock.c faillock_config.c ++faillock_SOURCES = main.c faillock.c faillock_config.c + + if ENABLE_REGENERATE_MAN + noinst_DATA = README +diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c +--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file 2022-05-26 10:57:11.727067606 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c 2022-05-26 10:57:11.748067756 +0200 +@@ -38,7 +38,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -54,83 +53,50 @@ + #include + #include + ++#include "pam_inline.h" + #include "faillock.h" +- +-#define PAM_SM_AUTH +-#define PAM_SM_ACCOUNT ++#include "faillock_config.h" + + #define FAILLOCK_ACTION_PREAUTH 0 + #define FAILLOCK_ACTION_AUTHSUCC 1 + #define FAILLOCK_ACTION_AUTHFAIL 2 + +-#define FAILLOCK_FLAG_DENY_ROOT 0x1 +-#define FAILLOCK_FLAG_AUDIT 0x2 +-#define FAILLOCK_FLAG_SILENT 0x4 +-#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 +-#define FAILLOCK_FLAG_UNLOCKED 0x10 +-#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 +- +-#define MAX_TIME_INTERVAL 604800 /* 7 days */ +-#define FAILLOCK_CONF_MAX_LINELEN 1023 +-#define FAILLOCK_ERROR_CONF_OPEN -3 +-#define FAILLOCK_ERROR_CONF_MALFORMED -4 +- +-#define PATH_PASSWD "/etc/passwd" +- +-struct options { +- unsigned int action; +- unsigned int flags; +- unsigned short deny; +- unsigned int fail_interval; +- unsigned int unlock_time; +- unsigned int root_unlock_time; +- char *dir; +- const char *conf; +- const char *user; +- char *admin_group; +- int failures; +- uint64_t latest_time; +- uid_t uid; +- int is_admin; +- uint64_t now; +- int fatal_error; +-}; +- +-int read_config_file( +- pam_handle_t *pamh, +- struct options *opts, +- const char *cfgfile +-); +- +-void set_conf_opt( +- pam_handle_t *pamh, +- struct options *opts, +- const char *name, +- const char *value +-); +- +-static void ++static int + args_parse(pam_handle_t *pamh, int argc, const char **argv, + int flags, struct options *opts) + { + int i; ++ int config_arg_index = -1; + int rv; ++ const char *conf = NULL; ++ + memset(opts, 0, sizeof(*opts)); + +- opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR); +- opts->conf = FAILLOCK_DEFAULT_CONF; + opts->deny = 3; + opts->fail_interval = 900; + opts->unlock_time = 600; + opts->root_unlock_time = MAX_TIME_INTERVAL+1; + +- if ((rv=read_config_file(pamh, opts, opts->conf)) != PAM_SUCCESS) { +- pam_syslog(pamh, LOG_DEBUG, +- "Configuration file missing"); ++ for (i = 0; i < argc; ++i) { ++ const char *str = pam_str_skip_prefix(argv[i], "conf="); ++ ++ if (str != NULL) { ++ conf = str; ++ config_arg_index = i; ++ } ++ } ++ ++ if ((rv = read_config_file(pamh, opts, conf)) != PAM_SUCCESS) { ++ pam_syslog(pamh, LOG_ERR, ++ "Configuration file missing or broken"); ++ return rv; + } + + for (i = 0; i < argc; ++i) { +- if (strcmp(argv[i], "preauth") == 0) { ++ if (i == config_arg_index) { ++ continue; ++ } ++ else if (strcmp(argv[i], "preauth") == 0) { + opts->action = FAILLOCK_ACTION_PREAUTH; + } + else if (strcmp(argv[i], "authfail") == 0) { +@@ -163,226 +129,26 @@ args_parse(pam_handle_t *pamh, int argc, + if (flags & PAM_SILENT) + opts->flags |= FAILLOCK_FLAG_SILENT; + +- if (opts->dir == NULL) { +- pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); +- opts->fatal_error = 1; +- } +-} +- +-/* parse a single configuration file */ +-int +-read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) +-{ +- FILE *f; +- char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; +- +- f = fopen(cfgfile, "r"); +- if (f == NULL) { +- /* ignore non-existent default config file */ +- if (errno == ENOENT && strcmp(cfgfile, FAILLOCK_DEFAULT_CONF) == 0) +- return 0; +- return FAILLOCK_ERROR_CONF_OPEN; +- } +- +- while (fgets(linebuf, sizeof(linebuf), f) != NULL) { +- size_t len; +- char *ptr; +- char *name; +- int eq; +- +- len = strlen(linebuf); +- /* len cannot be 0 unless there is a bug in fgets */ +- if (len && linebuf[len - 1] != '\n' && !feof(f)) { +- (void) fclose(f); +- return FAILLOCK_ERROR_CONF_MALFORMED; +- } +- +- if ((ptr=strchr(linebuf, '#')) != NULL) { +- *ptr = '\0'; +- } else { +- ptr = linebuf + len; +- } +- +- /* drop terminating whitespace including the \n */ +- while (ptr > linebuf) { +- if (!isspace(*(ptr-1))) { +- *ptr = '\0'; +- break; +- } +- --ptr; +- } +- +- /* skip initial whitespace */ +- for (ptr = linebuf; isspace(*ptr); ptr++); +- if (*ptr == '\0') +- continue; +- +- /* grab the key name */ +- eq = 0; +- name = ptr; +- while (*ptr != '\0') { +- if (isspace(*ptr) || *ptr == '=') { +- eq = *ptr == '='; +- *ptr = '\0'; +- ++ptr; +- break; +- } +- ++ptr; +- } +- +- /* grab the key value */ +- while (*ptr != '\0') { +- if (*ptr != '=' || eq) { +- if (!isspace(*ptr)) { +- break; +- } +- } else { +- eq = 1; +- } +- ++ptr; +- } +- +- /* set the key:value pair on opts */ +- set_conf_opt(pamh, opts, name, ptr); +- } +- +- (void)fclose(f); ++ if (opts->fatal_error) ++ return PAM_BUF_ERR; + return PAM_SUCCESS; + } + +-void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value) +-{ +- if (strcmp(name, "dir") == 0) { +- if (value[0] != '/') { +- pam_syslog(pamh, LOG_ERR, +- "Tally directory is not absolute path (%s); keeping default", value); +- } else { +- free(opts->dir); +- opts->dir = strdup(value); +- } +- } +- else if (strcmp(name, "deny") == 0) { +- if (sscanf(value, "%hu", &opts->deny) != 1) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for deny argument"); +- } +- } +- else if (strcmp(name, "fail_interval") == 0) { +- unsigned int temp; +- if (sscanf(value, "%u", &temp) != 1 || +- temp > MAX_TIME_INTERVAL) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for fail_interval argument"); +- } else { +- opts->fail_interval = temp; +- } +- } +- else if (strcmp(name, "unlock_time") == 0) { +- unsigned int temp; +- +- if (strcmp(value, "never") == 0) { +- opts->unlock_time = 0; +- } +- else if (sscanf(value, "%u", &temp) != 1 || +- temp > MAX_TIME_INTERVAL) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for unlock_time argument"); +- } +- else { +- opts->unlock_time = temp; +- } +- } +- else if (strcmp(name, "root_unlock_time") == 0) { +- unsigned int temp; +- +- if (strcmp(value, "never") == 0) { +- opts->root_unlock_time = 0; +- } +- else if (sscanf(value, "%u", &temp) != 1 || +- temp > MAX_TIME_INTERVAL) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for root_unlock_time argument"); +- } else { +- opts->root_unlock_time = temp; +- } +- } +- else if (strcmp(name, "admin_group") == 0) { +- free(opts->admin_group); +- opts->admin_group = strdup(value); +- if (opts->admin_group == NULL) { +- opts->fatal_error = 1; +- pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); +- } +- } +- else if (strcmp(name, "even_deny_root") == 0) { +- opts->flags |= FAILLOCK_FLAG_DENY_ROOT; +- } +- else if (strcmp(name, "audit") == 0) { +- opts->flags |= FAILLOCK_FLAG_AUDIT; +- } +- else if (strcmp(name, "silent") == 0) { +- opts->flags |= FAILLOCK_FLAG_SILENT; +- } +- else if (strcmp(name, "no_log_info") == 0) { +- opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; +- } +- else if (strcmp(name, "local_users_only") == 0) { +- opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; +- } +- else { +- pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name); +- } +-} +- +-static int check_local_user (pam_handle_t *pamh, const char *user) ++static int ++check_local_user (pam_handle_t *pamh, const char *user) + { +- struct passwd pw, *pwp; +- char buf[4096]; +- int found = 0; +- FILE *fp; +- int errn; +- +- fp = fopen(PATH_PASSWD, "r"); +- if (fp == NULL) { +- pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", +- PATH_PASSWD); +- return -1; +- } +- +- for (;;) { +- errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp); +- if (errn == ERANGE) { +- pam_syslog(pamh, LOG_WARNING, "%s contains very long lines; corrupted?", +- PATH_PASSWD); +- /* we can continue here as next call will read further */ +- continue; +- } +- if (errn != 0) +- break; +- if (strcmp(pwp->pw_name, user) == 0) { +- found = 1; +- break; +- } +- } +- +- fclose (fp); +- +- if (errn != 0 && errn != ENOENT) { +- pam_syslog(pamh, LOG_ERR, "unable to enumerate local accounts: %m"); +- return -1; +- } else { +- return found; +- } ++ return pam_modutil_check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS; + } + +-static int get_pam_user(pam_handle_t *pamh, struct options *opts) ++static int ++get_pam_user(pam_handle_t *pamh, struct options *opts) + { + const char *user; + int rv; + struct passwd *pwd; + + if ((rv=pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { +- return rv; ++ return rv == PAM_CONV_AGAIN ? PAM_INCOMPLETE : rv; + } + + if (*user == '\0') { +@@ -391,10 +157,10 @@ static int get_pam_user(pam_handle_t *pa + + if ((pwd=pam_modutil_getpwnam(pamh, user)) == NULL) { + if (opts->flags & FAILLOCK_FLAG_AUDIT) { +- pam_syslog(pamh, LOG_ERR, "User unknown: %s", user); ++ pam_syslog(pamh, LOG_NOTICE, "User unknown: %s", user); + } + else { +- pam_syslog(pamh, LOG_ERR, "User unknown"); ++ pam_syslog(pamh, LOG_NOTICE, "User unknown"); + } + return PAM_IGNORE; + } +@@ -421,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct o + unsigned int i; + uint64_t latest_time; + int failures; ++ const char *dir = get_tally_dir(opts); + + opts->now = time(NULL); + +- tfd = open_tally(opts->dir, opts->user, opts->uid, 0); ++ tfd = open_tally(dir, opts->user, opts->uid, 0); + + *fd = tfd; + +@@ -446,7 +213,7 @@ check_tally(pam_handle_t *pamh, struct o + } + + latest_time = 0; +- for(i = 0; i < tallies->count; i++) { ++ for (i = 0; i < tallies->count; i++) { + if ((tallies->records[i].status & TALLY_STATUS_VALID) && + tallies->records[i].time > latest_time) + latest_time = tallies->records[i].time; +@@ -455,7 +222,7 @@ check_tally(pam_handle_t *pamh, struct o + opts->latest_time = latest_time; + + failures = 0; +- for(i = 0; i < tallies->count; i++) { ++ for (i = 0; i < tallies->count; i++) { + if ((tallies->records[i].status & TALLY_STATUS_VALID) && + latest_time - tallies->records[i].time < opts->fail_interval) { + ++failures; +@@ -498,9 +265,10 @@ static void + reset_tally(pam_handle_t *pamh, struct options *opts, int *fd) + { + int rv; ++ const char *dir = get_tally_dir(opts); + + if (*fd == -1) { +- *fd = open_tally(opts->dir, opts->user, opts->uid, 1); ++ *fd = open_tally(dir, opts->user, opts->uid, 1); + } + else { + while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR); +@@ -519,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct o + unsigned int oldest; + uint64_t oldtime; + const void *source = NULL; ++ const char *dir = get_tally_dir(opts); + + if (*fd == -1) { +- *fd = open_tally(opts->dir, opts->user, opts->uid, 1); ++ *fd = open_tally(dir, opts->user, opts->uid, 1); + } + if (*fd == -1) { + if (errno == EACCES) { +@@ -536,7 +305,7 @@ write_tally(pam_handle_t *pamh, struct o + failures = 0; + + for (i = 0; i < tallies->count; ++i) { +- if (tallies->records[i].time < oldtime) { ++ if (oldtime == 0 || tallies->records[i].time < oldtime) { + oldtime = tallies->records[i].time; + oldest = i; + } +@@ -630,16 +399,26 @@ faillock_message(pam_handle_t *pamh, str + left = opts->latest_time + opts->unlock_time - opts->now; + } + ++ pam_info(pamh, _("The account is locked due to %u failed logins."), ++ (unsigned int)opts->failures); + if (left > 0) { + left = (left + 59)/60; /* minutes */ + +- pam_info(pamh, _("Account temporarily locked due to %d failed logins"), +- opts->failures); +- pam_info(pamh, _("(%d minutes left to unlock)"), (int)left); +- } +- else { +- pam_info(pamh, _("Account locked due to %d failed logins"), +- opts->failures); ++#if defined HAVE_DNGETTEXT && defined ENABLE_NLS ++ pam_info( ++ pamh, ++ dngettext(PACKAGE, ++ "(%d minute left to unlock)", ++ "(%d minutes left to unlock)", ++ (int)left), ++ (int)left); ++#else ++ if (left == 1) ++ pam_info(pamh, _("(%d minute left to unlock)"), (int)left); ++ else ++ /* TRANSLATORS: only used if dngettext is not supported. */ ++ pam_info(pamh, _("(%d minutes left to unlock)"), (int)left); ++#endif + } + } + } +@@ -663,7 +442,7 @@ opts_cleanup(struct options *opts) + + /*---------------------------------------------------------------------*/ + +-PAM_EXTERN int ++int + pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char **argv) + { +@@ -673,13 +452,13 @@ pam_sm_authenticate(pam_handle_t *pamh, + + memset(&tallies, 0, sizeof(tallies)); + +- args_parse(pamh, argc, argv, flags, &opts); +- if (opts.fatal_error) { +- rv = PAM_BUF_ERR; ++ rv = args_parse(pamh, argc, argv, flags, &opts); ++ if (rv != PAM_SUCCESS) + goto err; +- } + +- pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ ++ if (!(opts.flags & FAILLOCK_FLAG_NO_DELAY)) { ++ pam_fail_delay(pamh, 2000000); /* 2 sec delay on failure */ ++ } + + if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { + goto err; +@@ -722,7 +501,7 @@ err: + + /*---------------------------------------------------------------------*/ + +-PAM_EXTERN int ++int + pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED, + int argc UNUSED, const char **argv UNUSED) + { +@@ -731,7 +510,7 @@ pam_sm_setcred(pam_handle_t *pamh UNUSED + + /*---------------------------------------------------------------------*/ + +-PAM_EXTERN int ++int + pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char **argv) + { +@@ -741,12 +520,10 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int + + memset(&tallies, 0, sizeof(tallies)); + +- args_parse(pamh, argc, argv, flags, &opts); ++ rv = args_parse(pamh, argc, argv, flags, &opts); + +- if (opts.fatal_error) { +- rv = PAM_BUF_ERR; ++ if (rv != PAM_SUCCESS) + goto err; +- } + + opts.action = FAILLOCK_ACTION_AUTHSUCC; + +@@ -770,28 +547,3 @@ err: + + /*-----------------------------------------------------------------------*/ + +-#ifdef PAM_STATIC +- +-/* static module data */ +- +-struct pam_module _pam_faillock_modstruct = { +- MODULE_NAME, +-#ifdef PAM_SM_AUTH +- pam_sm_authenticate, +- pam_sm_setcred, +-#else +- NULL, +- NULL, +-#endif +-#ifdef PAM_SM_ACCOUNT +- pam_sm_acct_mgmt, +-#else +- NULL, +-#endif +- NULL, +- NULL, +- NULL, +-}; +- +-#endif /* #ifdef PAM_STATIC */ +- +diff --git a/modules/pam_faillock/faillock.h b/modules/pam_faillock/faillock.h +index b22a9dfb..0ea0ffba 100644 +--- a/modules/pam_faillock/faillock.h ++++ b/modules/pam_faillock/faillock.h +diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock.h +--- Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100 ++++ Linux-PAM-1.5.1/modules/pam_faillock/faillock.h 2022-05-25 15:33:03.885551825 +0200 +@@ -67,7 +67,6 @@ struct tally_data { + }; + + #define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock" +-#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" + + int open_tally(const char *dir, const char *user, uid_t uid, int create); + int read_tally(int fd, struct tally_data *tallies); +diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c +index ddbb90e7..f46fca99 100644 +--- a/modules/pam_faillock/pam_faillock.c ++++ b/modules/pam_faillock/pam_faillock.c +@@ -134,10 +134,96 @@ args_parse(pam_handle_t *pamh, int argc, const char **argv, + return PAM_SUCCESS; + } + ++static int ++check_user_in_passwd(pam_handle_t *pamh, ++ const char *user_name, ++ const char *file_name) ++{ ++ int rc; ++ size_t user_len; ++ FILE *fp; ++ char line[BUFSIZ]; ++ ++ /* Validate the user name. */ ++ if ((user_len = strlen(user_name)) == 0) { ++ pam_syslog(pamh, LOG_NOTICE, "user name is not valid"); ++ return PAM_SERVICE_ERR; ++ } ++ ++ if (user_len > sizeof(line) - sizeof(":")) { ++ pam_syslog(pamh, LOG_NOTICE, "user name is too long"); ++ return PAM_SERVICE_ERR; ++ } ++ ++ if (strchr(user_name, ':') != NULL) { ++ /* ++ * "root:x" is not a local user name even if the passwd file ++ * contains a line starting with "root:x:". ++ */ ++ return PAM_PERM_DENIED; ++ } ++ ++ /* Open the passwd file. */ ++ if (file_name == NULL) { ++ file_name = "/etc/passwd"; ++ } ++ if ((fp = fopen(file_name, "r")) == NULL) { ++ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", file_name); ++ return PAM_SERVICE_ERR; ++ } ++ ++ /* ++ * Scan the file using fgets() instead of fgetpwent_r() because ++ * the latter is not flexible enough in handling long lines ++ * in passwd files. ++ */ ++ rc = PAM_PERM_DENIED; ++ while (fgets(line, sizeof(line), fp) != NULL) { ++ size_t line_len; ++ const char *str; ++ ++ /* ++ * Does this line start with the user name ++ * followed by a colon? ++ */ ++ if (strncmp(user_name, line, user_len) == 0 && ++ line[user_len] == ':') { ++ rc = PAM_SUCCESS; ++ /* ++ * Continue reading the file to avoid timing attacks. ++ */ ++ } ++ /* Has a newline been read? */ ++ line_len = strlen(line); ++ if (line_len < sizeof(line) - 1 || ++ line[line_len - 1] == '\n') { ++ /* Yes, continue with the next line. */ ++ continue; ++ } ++ ++ /* No, read till the end of this line first. */ ++ while ((str = fgets(line, sizeof(line), fp)) != NULL) { ++ line_len = strlen(line); ++ if (line_len == 0 || ++ line[line_len - 1] == '\n') { ++ break; ++ } ++ } ++ if (str == NULL) { ++ /* fgets returned NULL, we are done. */ ++ break; ++ } ++ /* Continue with the next line. */ ++ } ++ ++ fclose(fp); ++ return rc; ++} ++ + static int + check_local_user (pam_handle_t *pamh, const char *user) + { +- return pam_modutil_check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS; ++ return check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS; + } + + static int diff --git a/SOURCES/pam-1.3.1-faillock-update.patch b/SOURCES/pam-1.3.1-faillock-update.patch new file mode 100644 index 0000000..c001f48 --- /dev/null +++ b/SOURCES/pam-1.3.1-faillock-update.patch @@ -0,0 +1,1186 @@ +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.c +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-update 2019-10-16 16:49:27.026893768 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.c 2019-12-16 17:55:27.042001068 +0100 +@@ -1,5 +1,6 @@ + /* + * Copyright (c) 2010 Tomas Mraz ++ * Copyright (c) 2010, 2016, 2017 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -47,6 +48,8 @@ + + #include "faillock.h" + ++#define ignore_return(x) if (1==((int)x)) {;} ++ + int + open_tally (const char *dir, const char *user, uid_t uid, int create) + { +@@ -54,7 +57,7 @@ open_tally (const char *dir, const char + int flags = O_RDWR; + int fd; + +- if (strstr(user, "../") != NULL) ++ if (dir == NULL || strstr(user, "../") != NULL) + /* just a defensive programming as the user must be a + * valid user on the system anyway + */ +@@ -83,7 +86,7 @@ open_tally (const char *dir, const char + while (flock(fd, LOCK_EX) == -1 && errno == EINTR); + if (fstat(fd, &st) == 0) { + if (st.st_uid != uid) { +- fchown(fd, uid, -1); ++ ignore_return(fchown(fd, uid, -1)); + } + } + } +@@ -121,7 +124,7 @@ read_tally(int fd, struct tally_data *ta + if (count >= MAX_RECORDS) + break; + } +- while (chunk == CHUNK_SIZE); ++ while (chunk == CHUNK_SIZE); + + tallies->records = data; + tallies->count = count; +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml.faillock-update 2019-10-16 17:34:58.073276020 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml 2019-10-16 16:26:05.000000000 +0200 +@@ -0,0 +1,243 @@ ++ ++ ++ ++ ++ ++ ++ faillock.conf ++ 5 ++ Linux-PAM Manual ++ ++ ++ ++ faillock.conf ++ pam_faillock configuration file ++ ++ ++ ++ ++ DESCRIPTION ++ ++ faillock.conf provides a way to configure the ++ default settings for locking the user after multiple failed authentication attempts. ++ This file is read by the pam_faillock module and is the ++ preferred method over configuring pam_faillock directly. ++ ++ ++ The file has a very simple name = value format with possible comments ++ starting with # character. The whitespace at the beginning of line, end ++ of line, and around the = sign is ignored. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ The directory where the user files with the failure records are kept. The ++ default is /var/run/faillock. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Will log the user name into the system log if the user is not found. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't print informative messages to the user. Please note that when ++ this option is not used there will be difference in the authentication ++ behavior for users which exist on the system and non-existing users. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't log informative messages via syslog3. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Only track failed user authentications attempts for local users ++ in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users. ++ The faillock8 ++ command will also no longer track user failed ++ authentication attempts. Enabling this option will prevent a ++ double-lockout scenario where a user is locked out locally and ++ in the centralized mechanism. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Deny access if the number of consecutive authentication failures ++ for this user during the recent interval exceeds ++ n. The default is 3. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The length of the interval during which the consecutive ++ authentication failures must happen for the user account ++ lock out is n seconds. ++ The default is 900 (15 minutes). ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The access will be reenabled after ++ n seconds after the lock out. ++ The value 0 has the same meaning as value ++ never - the access ++ will not be reenabled without resetting the faillock ++ entries by the faillock8 command. ++ The default is 600 (10 minutes). ++ ++ ++ Note that the default directory that pam_faillock ++ uses is usually cleared on system boot so the access will be also reenabled ++ after system reboot. If that is undesirable a different tally directory ++ must be set with the option. ++ ++ ++ Also note that it is usually undesirable to permanently lock ++ out the users as they can become easily a target of denial of service ++ attack unless the usernames are random and kept secret to potential ++ attackers. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Root account can become locked as well as regular accounts. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This option implies option. ++ Allow access after n seconds ++ to root account after the account is locked. In case the ++ option is not specified the value is the same as of the ++ option. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ If a group name is specified with this option, members ++ of the group will be handled by this module the same as ++ the root account (the options ++ and will apply to them. ++ By default the option is not set. ++ ++ ++ ++ ++ ++ ++ ++ EXAMPLES ++ ++ /etc/security/faillock.conf file example: ++ ++ ++deny=4 ++unlock_time=1200 ++silent ++ ++ ++ ++ ++ FILES ++ ++ ++ /etc/security/faillock.conf ++ ++ the config file for custom options ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ faillock8 ++ , ++ ++ pam_faillock8 ++ , ++ ++ pam.conf5 ++ , ++ ++ pam.d5 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ pam_faillock was written by Tomas Mraz. The support for faillock.conf was written by Brian Ward. ++ ++ ++ ++ +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.faillock-update 2019-10-16 17:34:50.607405060 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf 2019-10-16 16:26:05.000000000 +0200 +@@ -0,0 +1,62 @@ ++# Configuration for locking the user after multiple failed ++# authentication attempts. ++# ++# The directory where the user files with the failure records are kept. ++# The default is /var/run/faillock. ++# dir = /var/run/faillock ++# ++# Will log the user name into the system log if the user is not found. ++# Enabled if option is present. ++# audit ++# ++# Don't print informative messages. ++# Enabled if option is present. ++# silent ++# ++# Don't log informative messages via syslog. ++# Enabled if option is present. ++# no_log_info ++# ++# Only track failed user authentications attempts for local users ++# in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users. ++# The `faillock` command will also no longer track user failed ++# authentication attempts. Enabling this option will prevent a ++# double-lockout scenario where a user is locked out locally and ++# in the centralized mechanism. ++# Enabled if option is present. ++# local_users_only ++# ++# Deny access if the number of consecutive authentication failures ++# for this user during the recent interval exceeds n tries. ++# The default is 3. ++# deny = 3 ++# ++# The length of the interval during which the consecutive ++# authentication failures must happen for the user account ++# lock out is n seconds. ++# The default is 900 (15 minutes). ++# fail_interval = 900 ++# ++# The access will be reenabled after n seconds after the lock out. ++# The value 0 has the same meaning as value `never` - the access ++# will not be reenabled without resetting the faillock ++# entries by the `faillock` command. ++# The default is 600 (10 minutes). ++# unlock_time = 600 ++# ++# Root account can become locked as well as regular accounts. ++# Enabled if option is present. ++# even_deny_root ++# ++# This option implies the `even_deny_root` option. ++# Allow access after n seconds to root account after the ++# account is locked. In case the option is not specified ++# the value is the same as of the `unlock_time` option. ++# root_unlock_time = 900 ++# ++# If a group name is specified with this option, members ++# of the group will be handled by this module the same as ++# the root account (the options `even_deny_root>` and ++# `root_unlock_time` will apply to them. ++# By default, the option is not set. ++# admin_group = +diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.h.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.h +--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.h.faillock-update 2019-10-16 16:49:27.026893768 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.h 2019-10-16 16:51:40.431628566 +0200 +@@ -65,6 +65,7 @@ struct tally_data { + }; + + #define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock" ++#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" + + int open_tally(const char *dir, const char *user, uid_t uid, int create); + int read_tally(int fd, struct tally_data *tallies); +diff -up Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am +--- Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-update 2019-10-16 16:49:27.026893768 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am 2019-10-16 16:50:15.065078080 +0200 +@@ -1,6 +1,6 @@ + # + # Copyright (c) 2005, 2006, 2007, 2009 Thorsten Kukuk +-# Copyright (c) 2008 Red Hat, Inc. ++# Copyright (c) 2008, 2018 Red Hat, Inc. + # Copyright (c) 2010 Tomas Mraz + # + +@@ -9,8 +9,8 @@ MAINTAINERCLEANFILES = $(MANS) README + + EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_faillock + +-man_MANS = pam_faillock.8 faillock.8 +-XMLS = README.xml pam_faillock.8.xml faillock.8.xml ++man_MANS = pam_faillock.8 faillock.8 faillock.conf.5 ++XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml + + TESTS = tst-pam_faillock + +@@ -31,6 +31,8 @@ endif + faillock_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + faillock_LDADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT) + ++secureconf_DATA = faillock.conf ++ + securelib_LTLIBRARIES = pam_faillock.la + sbin_PROGRAMS = faillock + +diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml +--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml.faillock-update 2019-10-16 16:49:27.030893701 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml 2019-10-16 16:53:39.544606052 +0200 +@@ -126,141 +126,13 @@ + + + +- +- +- +- +- +- +- The directory where the user files with the failure records are kept. The +- default is /var/run/faillock. +- +- +- +- +- +- +- +- +- +- Will log the user name into the system log if the user is not found. +- +- +- +- +- +- +- +- +- +- Don't print informative messages. This option is implicite +- in the authfail and authsucc +- functions. +- +- +- +- +- +- +- +- +- +- Don't log informative messages via syslog3. +- +- +- +- +- +- +- +- +- +- Deny access if the number of consecutive authentication failures +- for this user during the recent interval exceeds +- n. The default is 3. +- +- +- +- +- +- +- +- +- +- The length of the interval during which the consecutive +- authentication failures must happen for the user account +- lock out is n seconds. +- The default is 900 (15 minutes). +- +- +- +- +- +- +- +- +- +- The access will be reenabled after +- n seconds after the lock out. +- The value 0 has the same meaning as value +- never - the access +- will not be reenabled without resetting the faillock +- entries by the faillock8 command. +- The default is 600 (10 minutes). +- +- +- Note that the default directory that pam_faillock +- uses is usually cleared on system boot so the access will be also reenabled +- after system reboot. If that is undesirable a different tally directory +- must be set with the option. +- +- +- Also note that it is usually undesirable to permanently lock +- out the users as they can become easily a target of denial of service +- attack unless the usernames are random and kept secret to potential +- attackers. +- +- +- +- +- +- +- +- +- +- Root account can become locked as well as regular accounts. +- +- +- +- +- +- +- +- +- +- This option implies option. +- Allow access after n seconds +- to root account after the account is locked. In case the +- option is not specified the value is the same as of the +- option. +- +- +- +- +- +- +- +- +- +- If a group name is specified with this option, members +- of the group will be handled by this module the same as +- the root account (the options +- and will apply to them. +- By default the option is not set. +- +- +- + ++ ++ The options for configuring the module behavior are described in the ++ faillock.conf5 ++ manual page. The options specified on the module command ++ line override the values from the configuration file. ++ + + + +@@ -306,19 +178,23 @@ + + NOTES + +- pam_faillock setup in the PAM stack is different ++ Configuring options on the module command line is not recommend. The ++ /etc/security/faillock.conf should be used instead. ++ ++ ++ The setup of pam_faillock in the PAM stack is different + from the pam_tally2 module setup. + + +- The individual files with the failure records are created as owned by ++ Individual files with the failure records are created as owned by + the user. This allows pam_faillock.so module + to work correctly when it is called from a screensaver. + + + Note that using the module in without the +- option or with requisite +- control field leaks an information about existence or +- non-existence of an user account in the system because ++ option specified in /etc/security/faillock.conf ++ or with requisite control field leaks an information about ++ existence or non-existence of an user account in the system because + the failures are not recorded for the unknown users. The message + about the user account being locked is never displayed for nonexisting + user accounts allowing the adversary to infer that a particular account +@@ -341,15 +217,26 @@ + be added to tell the user that his login is blocked by the module and also to abort + the authentication without even asking for password in such case. + ++ ++ /etc/security/faillock.conf file example: ++ ++ ++deny=4 ++unlock_time=1200 ++silent ++ ++ ++ /etc/pam.d/config file example: ++ + + auth required pam_securetty.so + auth required pam_env.so + auth required pam_nologin.so +-# optionally call: auth requisite pam_faillock.so preauth deny=4 even_deny_root unlock_time=1200 ++# optionally call: auth requisite pam_faillock.so preauth + # to display the message about account being locked + auth [success=1 default=bad] pam_unix.so +-auth [default=die] pam_faillock.so authfail deny=4 even_deny_root unlock_time=1200 +-auth sufficient pam_faillock.so authsucc deny=4 even_deny_root unlock_time=1200 ++auth [default=die] pam_faillock.so authfail ++auth sufficient pam_faillock.so authsucc + auth required pam_deny.so + account required pam_unix.so + password required pam_unix.so shadow +@@ -361,17 +248,18 @@ session required pam_selinux.so o + + In the second example the module is called both in the auth + and account phases and the module gives the authenticating +- user message when the account is locked ++ user message when the account is locked if option is not ++ specified in the faillock.conf. + + + auth required pam_securetty.so + auth required pam_env.so + auth required pam_nologin.so +-auth required pam_faillock.so preauth silent deny=4 even_deny_root unlock_time=1200 ++auth required pam_faillock.so preauth + # optionally use requisite above if you do not want to prompt for the password +-# on locked accounts, possibly with removing the silent option as well ++# on locked accounts + auth sufficient pam_unix.so +-auth [default=die] pam_faillock.so authfail deny=4 even_deny_root unlock_time=1200 ++auth [default=die] pam_faillock.so authfail + auth required pam_deny.so + account required pam_faillock.so + # if you drop the above call to pam_faillock.so the lock will be done also +@@ -394,6 +282,12 @@ session required pam_selinux.so o + the files logging the authentication failures for users + + ++ ++ /etc/security/faillock.conf ++ ++ the config file for pam_faillock options ++ ++ + + + +@@ -404,6 +298,9 @@ session required pam_selinux.so o + faillock8 + , + ++ faillock.conf5 ++ , ++ + pam.conf5 + , + +diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c +--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-update 2019-10-16 16:49:27.030893701 +0200 ++++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c 2019-12-16 17:55:11.403270018 +0100 +@@ -1,5 +1,6 @@ + /* +- * Copyright (c) 2010, 2017 Tomas Mraz ++ * Copyright (c) 2010, 2017, 2019 Tomas Mraz ++ * Copyright (c) 2010, 2017, 2019 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -43,6 +44,7 @@ + #include + #include + #include ++#include + + #ifdef HAVE_LIBAUDIT + #include +@@ -66,8 +68,14 @@ + #define FAILLOCK_FLAG_SILENT 0x4 + #define FAILLOCK_FLAG_NO_LOG_INFO 0x8 + #define FAILLOCK_FLAG_UNLOCKED 0x10 ++#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 + + #define MAX_TIME_INTERVAL 604800 /* 7 days */ ++#define FAILLOCK_CONF_MAX_LINELEN 1023 ++#define FAILLOCK_ERROR_CONF_OPEN -3 ++#define FAILLOCK_ERROR_CONF_MALFORMED -4 ++ ++#define PATH_PASSWD "/etc/passwd" + + struct options { + unsigned int action; +@@ -76,117 +84,295 @@ struct options { + unsigned int fail_interval; + unsigned int unlock_time; + unsigned int root_unlock_time; +- const char *dir; ++ char *dir; ++ const char *conf; + const char *user; +- const char *admin_group; ++ char *admin_group; + int failures; + uint64_t latest_time; + uid_t uid; + int is_admin; + uint64_t now; ++ int fatal_error; + }; + ++int read_config_file( ++ pam_handle_t *pamh, ++ struct options *opts, ++ const char *cfgfile ++); ++ ++void set_conf_opt( ++ pam_handle_t *pamh, ++ struct options *opts, ++ const char *name, ++ const char *value ++); ++ + static void + args_parse(pam_handle_t *pamh, int argc, const char **argv, + int flags, struct options *opts) + { + int i; ++ int rv; + memset(opts, 0, sizeof(*opts)); + +- opts->dir = FAILLOCK_DEFAULT_TALLYDIR; ++ opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR); ++ opts->conf = FAILLOCK_DEFAULT_CONF; + opts->deny = 3; + opts->fail_interval = 900; + opts->unlock_time = 600; + opts->root_unlock_time = MAX_TIME_INTERVAL+1; + +- for (i = 0; i < argc; ++i) { ++ if ((rv=read_config_file(pamh, opts, opts->conf)) != PAM_SUCCESS) { ++ pam_syslog(pamh, LOG_DEBUG, ++ "Configuration file missing"); ++ } + +- if (strncmp(argv[i], "dir=", 4) == 0) { +- if (argv[i][4] != '/') { +- pam_syslog(pamh, LOG_ERR, +- "Tally directory is not absolute path (%s); keeping default", argv[i]); +- } else { +- opts->dir = argv[i]+4; +- } +- } +- else if (strncmp(argv[i], "deny=", 5) == 0) { +- if (sscanf(argv[i]+5, "%hu", &opts->deny) != 1) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for deny argument"); +- } +- } +- else if (strncmp(argv[i], "fail_interval=", 14) == 0) { +- unsigned int temp; +- if (sscanf(argv[i]+14, "%u", &temp) != 1 || +- temp > MAX_TIME_INTERVAL) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for fail_interval argument"); +- } else { +- opts->fail_interval = temp; +- } ++ for (i = 0; i < argc; ++i) { ++ if (strcmp(argv[i], "preauth") == 0) { ++ opts->action = FAILLOCK_ACTION_PREAUTH; ++ } ++ else if (strcmp(argv[i], "authfail") == 0) { ++ opts->action = FAILLOCK_ACTION_AUTHFAIL; ++ } ++ else if (strcmp(argv[i], "authsucc") == 0) { ++ opts->action = FAILLOCK_ACTION_AUTHSUCC; + } +- else if (strncmp(argv[i], "unlock_time=", 12) == 0) { +- unsigned int temp; ++ else { ++ char buf[FAILLOCK_CONF_MAX_LINELEN + 1]; ++ char *val; + +- if (strcmp(argv[i]+12, "never") == 0) { +- opts->unlock_time = 0; +- } +- else if (sscanf(argv[i]+12, "%u", &temp) != 1 || +- temp > MAX_TIME_INTERVAL) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for unlock_time argument"); ++ strncpy(buf, argv[i], sizeof(buf) - 1); ++ buf[sizeof(buf) - 1] = '\0'; ++ ++ val = strchr(buf, '='); ++ if (val != NULL) { ++ *val = '\0'; ++ ++val; + } + else { +- opts->unlock_time = temp; ++ val = buf + sizeof(buf) - 1; + } ++ set_conf_opt(pamh, opts, buf, val); + } +- else if (strncmp(argv[i], "root_unlock_time=", 17) == 0) { +- unsigned int temp; ++ } + +- if (strcmp(argv[i]+17, "never") == 0) { +- opts->root_unlock_time = 0; +- } +- else if (sscanf(argv[i]+17, "%u", &temp) != 1 || +- temp > MAX_TIME_INTERVAL) { +- pam_syslog(pamh, LOG_ERR, +- "Bad number supplied for root_unlock_time argument"); ++ if (opts->root_unlock_time == MAX_TIME_INTERVAL+1) ++ opts->root_unlock_time = opts->unlock_time; ++ if (flags & PAM_SILENT) ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++ ++ if (opts->dir == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); ++ opts->fatal_error = 1; ++ } ++} ++ ++/* parse a single configuration file */ ++int ++read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) ++{ ++ FILE *f; ++ char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; ++ ++ f = fopen(cfgfile, "r"); ++ if (f == NULL) { ++ /* ignore non-existent default config file */ ++ if (errno == ENOENT && strcmp(cfgfile, FAILLOCK_DEFAULT_CONF) == 0) ++ return 0; ++ return FAILLOCK_ERROR_CONF_OPEN; ++ } ++ ++ while (fgets(linebuf, sizeof(linebuf), f) != NULL) { ++ size_t len; ++ char *ptr; ++ char *name; ++ int eq; ++ ++ len = strlen(linebuf); ++ /* len cannot be 0 unless there is a bug in fgets */ ++ if (len && linebuf[len - 1] != '\n' && !feof(f)) { ++ (void) fclose(f); ++ return FAILLOCK_ERROR_CONF_MALFORMED; ++ } ++ ++ if ((ptr=strchr(linebuf, '#')) != NULL) { ++ *ptr = '\0'; ++ } else { ++ ptr = linebuf + len; ++ } ++ ++ /* drop terminating whitespace including the \n */ ++ while (ptr > linebuf) { ++ if (!isspace(*(ptr-1))) { ++ *ptr = '\0'; ++ break; ++ } ++ --ptr; ++ } ++ ++ /* skip initial whitespace */ ++ for (ptr = linebuf; isspace(*ptr); ptr++); ++ if (*ptr == '\0') ++ continue; ++ ++ /* grab the key name */ ++ eq = 0; ++ name = ptr; ++ while (*ptr != '\0') { ++ if (isspace(*ptr) || *ptr == '=') { ++ eq = *ptr == '='; ++ *ptr = '\0'; ++ ++ptr; ++ break; ++ } ++ ++ptr; ++ } ++ ++ /* grab the key value */ ++ while (*ptr != '\0') { ++ if (*ptr != '=' || eq) { ++ if (!isspace(*ptr)) { ++ break; ++ } + } else { +- opts->root_unlock_time = temp; ++ eq = 1; + } ++ ++ptr; + } +- else if (strncmp(argv[i], "admin_group=", 12) == 0) { +- opts->admin_group = argv[i] + 12; ++ ++ /* set the key:value pair on opts */ ++ set_conf_opt(pamh, opts, name, ptr); ++ } ++ ++ (void)fclose(f); ++ return PAM_SUCCESS; ++} ++ ++void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value) ++{ ++ if (strcmp(name, "dir") == 0) { ++ if (value[0] != '/') { ++ pam_syslog(pamh, LOG_ERR, ++ "Tally directory is not absolute path (%s); keeping default", value); ++ } else { ++ free(opts->dir); ++ opts->dir = strdup(value); + } +- else if (strcmp(argv[i], "preauth") == 0) { +- opts->action = FAILLOCK_ACTION_PREAUTH; ++ } ++ else if (strcmp(name, "deny") == 0) { ++ if (sscanf(value, "%hu", &opts->deny) != 1) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for deny argument"); ++ } ++ } ++ else if (strcmp(name, "fail_interval") == 0) { ++ unsigned int temp; ++ if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for fail_interval argument"); ++ } else { ++ opts->fail_interval = temp; + } +- else if (strcmp(argv[i], "authfail") == 0) { +- opts->action = FAILLOCK_ACTION_AUTHFAIL; ++ } ++ else if (strcmp(name, "unlock_time") == 0) { ++ unsigned int temp; ++ ++ if (strcmp(value, "never") == 0) { ++ opts->unlock_time = 0; + } +- else if (strcmp(argv[i], "authsucc") == 0) { +- opts->action = FAILLOCK_ACTION_AUTHSUCC; ++ else if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for unlock_time argument"); + } +- else if (strcmp(argv[i], "even_deny_root") == 0) { +- opts->flags |= FAILLOCK_FLAG_DENY_ROOT; ++ else { ++ opts->unlock_time = temp; + } +- else if (strcmp(argv[i], "audit") == 0) { +- opts->flags |= FAILLOCK_FLAG_AUDIT; ++ } ++ else if (strcmp(name, "root_unlock_time") == 0) { ++ unsigned int temp; ++ ++ if (strcmp(value, "never") == 0) { ++ opts->root_unlock_time = 0; + } +- else if (strcmp(argv[i], "silent") == 0) { +- opts->flags |= FAILLOCK_FLAG_SILENT; ++ else if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for root_unlock_time argument"); ++ } else { ++ opts->root_unlock_time = temp; + } +- else if (strcmp(argv[i], "no_log_info") == 0) { +- opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; ++ } ++ else if (strcmp(name, "admin_group") == 0) { ++ free(opts->admin_group); ++ opts->admin_group = strdup(value); ++ if (opts->admin_group == NULL) { ++ opts->fatal_error = 1; ++ pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); + } +- else { +- pam_syslog(pamh, LOG_ERR, "Unknown option: %s", argv[i]); ++ } ++ else if (strcmp(name, "even_deny_root") == 0) { ++ opts->flags |= FAILLOCK_FLAG_DENY_ROOT; ++ } ++ else if (strcmp(name, "audit") == 0) { ++ opts->flags |= FAILLOCK_FLAG_AUDIT; ++ } ++ else if (strcmp(name, "silent") == 0) { ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++ } ++ else if (strcmp(name, "no_log_info") == 0) { ++ opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; ++ } ++ else if (strcmp(name, "local_users_only") == 0) { ++ opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; ++ } ++ else { ++ pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name); ++ } ++} ++ ++static int check_local_user (pam_handle_t *pamh, const char *user) ++{ ++ struct passwd pw, *pwp; ++ char buf[4096]; ++ int found = 0; ++ FILE *fp; ++ int errn; ++ ++ fp = fopen(PATH_PASSWD, "r"); ++ if (fp == NULL) { ++ pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", ++ PATH_PASSWD); ++ return -1; ++ } ++ ++ for (;;) { ++ errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp); ++ if (errn == ERANGE) { ++ pam_syslog(pamh, LOG_WARNING, "%s contains very long lines; corrupted?", ++ PATH_PASSWD); ++ /* we can continue here as next call will read further */ ++ continue; ++ } ++ if (errn != 0) ++ break; ++ if (strcmp(pwp->pw_name, user) == 0) { ++ found = 1; ++ break; + } + } + +- if (opts->root_unlock_time == MAX_TIME_INTERVAL+1) +- opts->root_unlock_time = opts->unlock_time; +- if (flags & PAM_SILENT) +- opts->flags |= FAILLOCK_FLAG_SILENT; ++ fclose (fp); ++ ++ if (errn != 0 && errn != ENOENT) { ++ pam_syslog(pamh, LOG_ERR, "unable to enumerate local accounts: %m"); ++ return -1; ++ } else { ++ return found; ++ } + } + + static int get_pam_user(pam_handle_t *pamh, struct options *opts) +@@ -393,7 +579,7 @@ write_tally(pam_handle_t *pamh, struct o + + strncpy(tallies->records[oldest].source, source, sizeof(tallies->records[oldest].source)); + /* source does not have to be null terminated */ +- ++ + tallies->records[oldest].time = opts->now; + + ++failures; +@@ -468,6 +654,13 @@ tally_cleanup(struct tally_data *tallies + free(tallies->records); + } + ++static void ++opts_cleanup(struct options *opts) ++{ ++ free(opts->dir); ++ free(opts->admin_group); ++} ++ + /*---------------------------------------------------------------------*/ + + PAM_EXTERN int +@@ -481,39 +674,49 @@ pam_sm_authenticate(pam_handle_t *pamh, + memset(&tallies, 0, sizeof(tallies)); + + args_parse(pamh, argc, argv, flags, &opts); ++ if (opts.fatal_error) { ++ rv = PAM_BUF_ERR; ++ goto err; ++ } + + pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ + + if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { +- return rv; ++ goto err; + } + +- switch (opts.action) { +- case FAILLOCK_ACTION_PREAUTH: +- rv = check_tally(pamh, &opts, &tallies, &fd); +- if (rv == PAM_AUTH_ERR && !(opts.flags & FAILLOCK_FLAG_SILENT)) { +- faillock_message(pamh, &opts); +- } +- break; +- +- case FAILLOCK_ACTION_AUTHSUCC: +- rv = check_tally(pamh, &opts, &tallies, &fd); +- if (rv == PAM_SUCCESS) { +- reset_tally(pamh, &opts, &fd); +- } +- break; +- +- case FAILLOCK_ACTION_AUTHFAIL: +- rv = check_tally(pamh, &opts, &tallies, &fd); +- if (rv == PAM_SUCCESS) { +- rv = PAM_IGNORE; /* this return value should be ignored */ +- write_tally(pamh, &opts, &tallies, &fd); +- } +- break; ++ if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) || ++ check_local_user (pamh, opts.user) != 0) { ++ switch (opts.action) { ++ case FAILLOCK_ACTION_PREAUTH: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_AUTH_ERR && !(opts.flags & FAILLOCK_FLAG_SILENT)) { ++ faillock_message(pamh, &opts); ++ } ++ break; ++ ++ case FAILLOCK_ACTION_AUTHSUCC: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_SUCCESS) { ++ reset_tally(pamh, &opts, &fd); ++ } ++ break; ++ ++ case FAILLOCK_ACTION_AUTHFAIL: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_SUCCESS) { ++ rv = PAM_IGNORE; /* this return value should be ignored */ ++ write_tally(pamh, &opts, &tallies, &fd); ++ } ++ break; ++ } + } + + tally_cleanup(&tallies, fd); + ++err: ++ opts_cleanup(&opts); ++ + return rv; + } + +@@ -540,18 +743,29 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int + + args_parse(pamh, argc, argv, flags, &opts); + ++ if (opts.fatal_error) { ++ rv = PAM_BUF_ERR; ++ goto err; ++ } ++ + opts.action = FAILLOCK_ACTION_AUTHSUCC; + + if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { +- return rv; ++ goto err; + } + +- check_tally(pamh, &opts, &tallies, &fd); /* for auditing */ +- reset_tally(pamh, &opts, &fd); ++ if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) || ++ check_local_user (pamh, opts.user) != 0) { ++ check_tally(pamh, &opts, &tallies, &fd); /* for auditing */ ++ reset_tally(pamh, &opts, &fd); ++ } + + tally_cleanup(&tallies, fd); + +- return PAM_SUCCESS; ++err: ++ opts_cleanup(&opts); ++ ++ return rv; + } + + /*-----------------------------------------------------------------------*/ diff --git a/SOURCES/pam-1.3.1-fds-closing.patch b/SOURCES/pam-1.3.1-fds-closing.patch new file mode 100644 index 0000000..7f5f772 --- /dev/null +++ b/SOURCES/pam-1.3.1-fds-closing.patch @@ -0,0 +1,70 @@ +diff -up Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c +--- Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c 2019-10-16 16:07:31.259021159 +0200 +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + /* + * Creates a pipe, closes its write end, redirects fd to its read end. +@@ -116,27 +117,45 @@ redirect_out(pam_handle_t *pamh, enum pa + static void + close_fds(void) + { ++ DIR *dir = NULL; ++ struct dirent *dent; ++ int dfd = -1; ++ int fd; ++ struct rlimit rlim; ++ + /* + * An arbitrary upper limit for the maximum file descriptor number + * returned by RLIMIT_NOFILE. + */ +- const int MAX_FD_NO = 65535; ++ const unsigned int MAX_FD_NO = 65535; + + /* The lower limit is the same as for _POSIX_OPEN_MAX. */ +- const int MIN_FD_NO = 20; ++ const unsigned int MIN_FD_NO = 20; + +- int fd; +- struct rlimit rlim; +- +- if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO) +- fd = MAX_FD_NO; +- else if (rlim.rlim_max < MIN_FD_NO) +- fd = MIN_FD_NO; +- else +- fd = rlim.rlim_max - 1; ++ /* If /proc is mounted, we can optimize which fd can be closed. */ ++ if ((dir = opendir("/proc/self/fd")) != NULL) { ++ if ((dfd = dirfd(dir)) >= 0) { ++ while ((dent = readdir(dir)) != NULL) { ++ fd = atoi(dent->d_name); ++ if (fd > STDERR_FILENO && fd != dfd) ++ close(fd); ++ } ++ } ++ closedir(dir); ++ } ++ ++ /* If /proc isn't available, fallback to the previous behavior. */ ++ if (dfd < 0) { ++ if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO) ++ fd = MAX_FD_NO; ++ else if (rlim.rlim_max < MIN_FD_NO) ++ fd = MIN_FD_NO; ++ else ++ fd = rlim.rlim_max - 1; + +- for (; fd > STDERR_FILENO; --fd) +- close(fd); ++ for (; fd > STDERR_FILENO; --fd) ++ close(fd); ++ } + } + + int diff --git a/SOURCES/pam-1.3.1-inline.patch b/SOURCES/pam-1.3.1-inline.patch new file mode 100644 index 0000000..65dfa26 --- /dev/null +++ b/SOURCES/pam-1.3.1-inline.patch @@ -0,0 +1,105 @@ +diff -up Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.inline Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h +--- Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.inline 2022-05-26 10:44:31.702623614 +0200 ++++ Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h 2022-05-26 10:44:31.703623621 +0200 +@@ -44,4 +44,17 @@ + # define DIAG_POP_IGNORE_CAST_ALIGN /* empty */ + #endif + ++/* ++ * Evaluates to ++ * 1, if the given two types are known to be the same ++ * 0, otherwise. ++ */ ++#if PAM_GNUC_PREREQ(3, 0) ++# define PAM_IS_SAME_TYPE(x_, y_) \ ++ __builtin_types_compatible_p(__typeof__(x_), __typeof__(y_)) ++#else ++/* Cannot tell whether these types are the same. */ ++# define PAM_IS_SAME_TYPE(x_, y_) 0 ++#endif ++ + #endif /* PAM_CC_COMPAT_H */ +diff -up Linux-PAM-1.3.1/libpam/include/pam_inline.h.inline Linux-PAM-1.3.1/libpam/include/pam_inline.h +--- Linux-PAM-1.3.1/libpam/include/pam_inline.h.inline 2022-05-26 10:44:31.703623621 +0200 ++++ Linux-PAM-1.3.1/libpam/include/pam_inline.h 2022-05-26 10:44:31.703623621 +0200 +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (c) 2020 Dmitry V. Levin ++ * ++ * Handy inline functions and macros providing some convenient functionality ++ * to libpam and its modules. ++ */ ++ ++#ifndef PAM_INLINE_H ++#define PAM_INLINE_H ++ ++#include "pam_cc_compat.h" ++#include ++ ++/* ++ * Evaluates to ++ * - a syntax error if the argument is 0, ++ * 0, otherwise. ++ */ ++#define PAM_FAIL_BUILD_ON_ZERO(e_) (sizeof(int[-1 + 2 * !!(e_)]) * 0) ++ ++/* ++ * Evaluates to ++ * 1, if the given type is known to be a non-array type ++ * 0, otherwise. ++ */ ++#define PAM_IS_NOT_ARRAY(a_) PAM_IS_SAME_TYPE((a_), &(a_)[0]) ++ ++/* ++ * Evaluates to ++ * - a syntax error if the argument is not an array, ++ * 0, otherwise. ++ */ ++#define PAM_MUST_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(!PAM_IS_NOT_ARRAY(a_)) ++ ++/* Evaluates to the number of elements in the specified array. */ ++#define PAM_ARRAY_SIZE(a_) (sizeof(a_) / sizeof((a_)[0]) + PAM_MUST_BE_ARRAY(a_)) ++ ++/* ++ * Returns NULL if STR does not start with PREFIX, ++ * or a pointer to the first char in STR after PREFIX. ++ * The length of PREFIX is specified by PREFIX_LEN. ++ */ ++static inline const char * ++pam_str_skip_prefix_len(const char *str, const char *prefix, size_t prefix_len) ++{ ++ return strncmp(str, prefix, prefix_len) ? NULL : str + prefix_len; ++} ++ ++#define pam_str_skip_prefix(str_, prefix_) \ ++ pam_str_skip_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) ++ ++/* ++ * Returns NULL if STR does not start with PREFIX ++ * (ignoring the case of the characters), ++ * or a pointer to the first char in STR after PREFIX. ++ * The length of PREFIX is specified by PREFIX_LEN. ++ */ ++static inline const char * ++pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix_len) ++{ ++ return strncasecmp(str, prefix, prefix_len) ? NULL : str + prefix_len; ++} ++ ++#define pam_str_skip_icase_prefix(str_, prefix_) \ ++ pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) ++ ++#endif /* PAM_INLINE_H */ +diff -up Linux-PAM-1.3.1/libpam/Makefile.am.inline Linux-PAM-1.3.1/libpam/Makefile.am +--- Linux-PAM-1.3.1/libpam/Makefile.am.inline 2022-05-26 10:44:31.702623614 +0200 ++++ Linux-PAM-1.3.1/libpam/Makefile.am 2022-05-26 10:45:21.146977780 +0200 +@@ -18,7 +18,8 @@ include_HEADERS = include/security/_pam_ + include/security/pam_ext.h include/security/pam_modutil.h + + noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \ +- pam_modutil_private.h include/pam_cc_compat.h ++ pam_modutil_private.h include/pam_cc_compat.h \ ++ include/pam_inline.h + + libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84 + libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@ diff --git a/SOURCES/pam-1.3.1-lastlog-no-showfailed.patch b/SOURCES/pam-1.3.1-lastlog-no-showfailed.patch new file mode 100644 index 0000000..6b68d9d --- /dev/null +++ b/SOURCES/pam-1.3.1-lastlog-no-showfailed.patch @@ -0,0 +1,82 @@ +From c426914fa166ffb0482b6f6ad659ddf17d5dfaa1 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Wed, 9 Jan 2019 23:41:16 +0200 +Subject: [PATCH] pam_lastlog: Improve silent option documentation + +The silent option explicitly silents only the last login message and not +bad logins. Add a note to the manual to make this clear. + +* modules/pam_lastlog/pam_lastlog.8.xml: Clearify "silent showfailed" +--- + modules/pam_lastlog/pam_lastlog.8.xml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml +index c8f247e..bc2e1be 100644 +--- a/modules/pam_lastlog/pam_lastlog.8.xml ++++ b/modules/pam_lastlog/pam_lastlog.8.xml +@@ -102,6 +102,7 @@ + + Don't inform the user about any previous login, + just update the /var/log/lastlog file. ++ This option does not affect display of bad login attempts. + + + +-- +2.20.1 + +From 7d036249a9772c546ede1f38ad68b3f1575216d6 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Sun, 6 Jan 2019 00:36:27 +0200 +Subject: [PATCH] pam_lastlog: Respect PAM_SILENT flag + +pam_lastlog module will not log info about failed login if the session +was opened with PAM_SILENT flag. + +Example use case enabled by this change: + + sudo --non-interactive program + +If this command is run by another program expecting specific output from +the command run by sudo, the unexpected info about failed logins will +break this program. + +* modules/pam_lastlog/pam_lastlog.c: Respect silent option. + (_pam_session_parse): Unset LASTLOG_BTMP if PAM_SILENT is set. +--- + modules/pam_lastlog/pam_lastlog.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c +index 18bf7be..e980c04 100644 +--- a/modules/pam_lastlog/pam_lastlog.c ++++ b/modules/pam_lastlog/pam_lastlog.c +@@ -135,11 +135,6 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) + { + int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP|LASTLOG_UPDATE); + +- /* does the appliction require quiet? */ +- if (flags & PAM_SILENT) { +- ctrl |= LASTLOG_QUIET; +- } +- + /* step through arguments */ + for (; argc-- > 0; ++argv) { + +@@ -168,6 +163,12 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) + } + } + ++ /* does the appliction require quiet? */ ++ if (flags & PAM_SILENT) { ++ ctrl |= LASTLOG_QUIET; ++ ctrl &= ~LASTLOG_BTMP; ++ } ++ + D(("ctrl = %o", ctrl)); + return ctrl; + } +-- +2.20.1 + diff --git a/SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch b/SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch new file mode 100644 index 0000000..1067d6f --- /dev/null +++ b/SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch @@ -0,0 +1,227 @@ +From 3a3e70739834cd5cbd17469907ef718c81ae40c0 Mon Sep 17 00:00:00 2001 +From: Carlos Santos +Date: Wed, 11 Sep 2019 11:50:28 -0300 +Subject: [PATCH] pam_lastlog: document the 'unlimited' option + +Signed-off-by: Carlos Santos +--- + modules/pam_lastlog/pam_lastlog.8.xml | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml +index bc2e1be..f10e94a 100644 +--- a/modules/pam_lastlog/pam_lastlog.8.xml ++++ b/modules/pam_lastlog/pam_lastlog.8.xml +@@ -48,6 +48,9 @@ + + inactive=<days> + ++ ++ unlimited ++ + + + +@@ -196,6 +199,18 @@ + + + ++ ++ ++ ++ ++ ++ ++ If the fsize limit is set, this option can be ++ used to override it, preventing failures on systems with large UID ++ values that lead lastlog to become a huge sparse file. ++ ++ ++ + + + +@@ -300,6 +315,9 @@ + + SEE ALSO + ++ ++ limits.conf5 ++ , + + pam.conf5 + , +-- +2.20.1 + +From 9349333a9ae958205294cd25e97fd6b4805bd82b Mon Sep 17 00:00:00 2001 +From: Carlos Santos +Date: Tue, 10 Sep 2019 23:08:30 -0300 +Subject: [PATCH] pam_lastlog: prevent crash due to reduced 'fsize' limit + +It a reduced fsize limit is set in /etc/security/limits.conf and +pam_limits is in use pam_lastlog may cause a crash, e.g. + + ----- begin /etc/pam.d/su ---- + auth sufficient pam_rootok.so + auth required pam_wheel.so use_uid + auth required pam_env.so + auth required pam_unix.so nullok + account required pam_unix.so + password required pam_unix.so nullok + session required pam_limits.so + session required pam_env.so + session required pam_unix.so + session optional pam_lastlog.so + ----- end /etc/pam.d/su ----- + + ----- begin /etc/security/limits.d/fsize.conf ----- + * soft fsize 1710 + * hard fsize 1710 + ----- end /etc/security/limits.d/fsize.conf ----- + + # id user1 + uid=1000(user1) gid=1000(user1) groups=1000(user1) + # su - user1 + Last login: Wed Sep 11 01:52:44 UTC 2019 on console + $ exit + # id user2 + uid=60000(user2) gid=60000(user2) groups=60000(user2) + # su - user2 + File size limit exceeded + +This happens because pam_limits sets RLIMIT_FSIZE before pam_lastlog +attempts to write /var/log/lastlog, leading to a SIGXFSZ signal. + +In order to fix this, and an 'unlimited' option, which leads to saving +the 'fsize' limit and set it to unlimited before writing lastlog. After +that, restore the saved value. If 'fsize' is already unlimited nothing +is done. + +Failing to set the 'fsize' limit is not a fatal error. With luck the +configured limit will suffice, so we try to write lastlog anyway, even +under the risk of dying due to a SIGXFSZ. + +Failing to restore the 'fsize' limit is a fatal error, since we don't +want to keep it unlimited. + +Signed-off-by: Carlos Santos +--- + modules/pam_lastlog/pam_lastlog.c | 66 ++++++++++++++++++++++++++----- + 1 file changed, 57 insertions(+), 9 deletions(-) + +diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c +index e980c04..a135c9f 100644 +--- a/modules/pam_lastlog/pam_lastlog.c ++++ b/modules/pam_lastlog/pam_lastlog.c +@@ -25,6 +25,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + +@@ -82,15 +84,16 @@ struct lastlog { + + /* argument parsing */ + +-#define LASTLOG_DATE 01 /* display the date of the last login */ +-#define LASTLOG_HOST 02 /* display the last host used (if set) */ +-#define LASTLOG_LINE 04 /* display the last terminal used */ +-#define LASTLOG_NEVER 010 /* display a welcome message for first login */ +-#define LASTLOG_DEBUG 020 /* send info to syslog(3) */ +-#define LASTLOG_QUIET 040 /* keep quiet about things */ +-#define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */ +-#define LASTLOG_BTMP 0200 /* display failed login info from btmp */ +-#define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */ ++#define LASTLOG_DATE 01 /* display the date of the last login */ ++#define LASTLOG_HOST 02 /* display the last host used (if set) */ ++#define LASTLOG_LINE 04 /* display the last terminal used */ ++#define LASTLOG_NEVER 010 /* display a welcome message for first login */ ++#define LASTLOG_DEBUG 020 /* send info to syslog(3) */ ++#define LASTLOG_QUIET 040 /* keep quiet about things */ ++#define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */ ++#define LASTLOG_BTMP 0200 /* display failed login info from btmp */ ++#define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */ ++#define LASTLOG_UNLIMITED 01000 /* unlimited file size (ignore 'fsize' limit) */ + + static int + _pam_auth_parse(pam_handle_t *pamh, int flags, int argc, const char **argv, +@@ -158,6 +161,8 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) + ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE); + } else if (!strcmp(*argv,"showfailed")) { + ctrl |= LASTLOG_BTMP; ++ } else if (!strcmp(*argv,"unlimited")) { ++ ctrl |= LASTLOG_UNLIMITED; + } else { + pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); + } +@@ -373,6 +378,12 @@ static int + last_login_write(pam_handle_t *pamh, int announce, int last_fd, + uid_t uid, const char *user) + { ++ static struct rlimit no_limit = { ++ RLIM_INFINITY, ++ RLIM_INFINITY ++ }; ++ struct rlimit old_limit; ++ int setrlimit_res; + struct flock last_lock; + struct lastlog last_login; + time_t ll_time; +@@ -427,6 +438,31 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, + sleep(LASTLOG_IGNORE_LOCK_TIME); + } + ++ /* ++ * Failing to set the 'fsize' limit is not a fatal error. We try to write ++ * lastlog anyway, under the risk of dying due to a SIGXFSZ. ++ */ ++ D(("setting limit for 'fsize'")); ++ ++ if ((announce & LASTLOG_UNLIMITED) == 0) { /* don't set to unlimted */ ++ setrlimit_res = -1; ++ } else if (getrlimit(RLIMIT_FSIZE, &old_limit) == 0) { ++ if (old_limit.rlim_cur == RLIM_INFINITY) { /* already unlimited */ ++ setrlimit_res = -1; ++ } else { ++ setrlimit_res = setrlimit(RLIMIT_FSIZE, &no_limit); ++ if (setrlimit_res != 0) ++ pam_syslog(pamh, LOG_WARNING, "Could not set limit for 'fsize': %m"); ++ } ++ } else { ++ setrlimit_res = -1; ++ if (errno == EINVAL) { ++ pam_syslog(pamh, LOG_INFO, "Limit for 'fsize' not supported: %m"); ++ } else { ++ pam_syslog(pamh, LOG_WARNING, "Could not get limit for 'fsize': %m"); ++ } ++ } ++ + D(("writing to the lastlog file")); + if (pam_modutil_write (last_fd, (char *) &last_login, + sizeof (last_login)) != sizeof(last_login)) { +@@ -434,6 +470,18 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, + retval = PAM_SERVICE_ERR; + } + ++ /* ++ * Failing to restore the 'fsize' limit is a fatal error. ++ */ ++ D(("restoring limit for 'fsize'")); ++ if (setrlimit_res == 0) { ++ setrlimit_res = setrlimit(RLIMIT_FSIZE, &old_limit); ++ if (setrlimit_res != 0) { ++ pam_syslog(pamh, LOG_ERR, "Could not restore limit for 'fsize': %m"); ++ retval = PAM_SERVICE_ERR; ++ } ++ } ++ + last_lock.l_type = F_UNLCK; + (void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */ + D(("unlocked")); +-- +2.20.1 + diff --git a/SOURCES/pam-1.3.1-motd-manpage.patch b/SOURCES/pam-1.3.1-motd-manpage.patch new file mode 100644 index 0000000..b8e2a1e --- /dev/null +++ b/SOURCES/pam-1.3.1-motd-manpage.patch @@ -0,0 +1,25 @@ +diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-manpage Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml +--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-manpage 2018-05-18 11:50:46.000000000 +0200 ++++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml 2019-12-19 10:29:36.243558251 +0100 +@@ -31,10 +31,19 @@ + + 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 /etc/motd file is ++ login. By default the /etc/motd file and ++ all files from /etc/motd.d are + shown. The message size is limited to 64KB. + +- ++ ++ To silence a message, ++ a symbolic link with target /dev/null ++ may be placed in /etc/motd.d with ++ the same filename as the message to be silenced. Example: ++ ++ ++ ln -sfn /dev/null /etc/motd.d/my_motd ++ + + + diff --git a/SOURCES/pam-1.3.1-namespace-gdm-doc.patch b/SOURCES/pam-1.3.1-namespace-gdm-doc.patch new file mode 100644 index 0000000..48c4961 --- /dev/null +++ b/SOURCES/pam-1.3.1-namespace-gdm-doc.patch @@ -0,0 +1,68 @@ +From 491e5500b6b3913f531574208274358a2df88659 Mon Sep 17 00:00:00 2001 +From: ikerexxe +Date: Mon, 5 Oct 2020 10:41:29 +0200 +Subject: [PATCH] pam_namespace: polyinstantiation refer to gdm doc + +modules/pam_namespace/pam_namespace.8.xml: delete obsolete information +about polyinstantiation and refer to gdm's documentation. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1861841 +--- + modules/pam_namespace/pam_namespace.8.xml | 41 ++--------------------- + 1 file changed, 2 insertions(+), 39 deletions(-) + +diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml +index f0f80d33..57c44c4b 100644 +--- a/modules/pam_namespace/pam_namespace.8.xml ++++ b/modules/pam_namespace/pam_namespace.8.xml +@@ -343,45 +343,8 @@ + + + +- To use polyinstantiation with graphical display manager gdm, insert the +- following line, before exit 0, in /etc/gdm/PostSession/Default: +- +- +- +- /usr/sbin/gdm-safe-restart +- +- +- +- This allows gdm to restart after each session and appropriately adjust +- namespaces of display manager and the X server. If polyinstantiation +- of /tmp is desired along with the graphical environment, then additional +- configuration changes are needed to address the interaction of X server +- and font server namespaces with their use of /tmp to create +- communication sockets. Please use the initialization script +- /etc/security/namespace.init to ensure that +- the X server and its clients can appropriately access the +- communication socket X0. Please refer to the sample instructions +- provided in the comment section of the instance initialization script +- /etc/security/namespace.init. In addition, +- perform the following changes to use graphical environment with +- polyinstantiation of /tmp: +- +- +- +- +- 1. Disable the use of font server by commenting out "FontPath" +- line in /etc/X11/xorg.conf. If you do want to use the font server +- then you will have to augment the instance initialization +- script to appropriately provide /tmp/.font-unix from the +- polyinstantiated /tmp. +- 2. Ensure that the gdm service is setup to use pam_namespace, +- as described above, by modifying /etc/pam.d/gdm. +- 3. Ensure that the display manager is configured to restart X server +- with each new session. This default setup can be verified by +- making sure that /usr/share/gdm/defaults.conf contains +- "AlwaysRestartServer=true", and it is not overridden by +- /etc/gdm/custom.conf. +- ++ To use polyinstantiation with graphical display manager gdm, please refer ++ to gdm's documentation. + + + +-- +2.26.2 + diff --git a/SOURCES/pam-1.3.1-namespace-mntopts.patch b/SOURCES/pam-1.3.1-namespace-mntopts.patch new file mode 100644 index 0000000..3249157 --- /dev/null +++ b/SOURCES/pam-1.3.1-namespace-mntopts.patch @@ -0,0 +1,131 @@ +diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml +index c7698cb..a94b49e 100644 +--- a/modules/pam_namespace/namespace.conf.5.xml ++++ b/modules/pam_namespace/namespace.conf.5.xml +@@ -122,9 +122,14 @@ + mntopts=value + - value of this flag is passed to the mount call when the tmpfs mount is + done. It allows for example the specification of the maximum size of the +- tmpfs instance that is created by the mount call. See +- mount8 +- for details. ++ tmpfs instance that is created by the mount call. In addition to ++ options specified in the ++ tmpfs5 ++ manual the nosuid, ++ noexec, and nodev flags ++ can be used to respectively disable setuid bit effect, disable running ++ executables, and disable devices to be interpreted on the mounted ++ tmpfs filesystem. + + + +diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c +index f541f89..660c7a1 100644 +--- a/modules/pam_namespace/pam_namespace.c ++++ b/modules/pam_namespace/pam_namespace.c +@@ -230,6 +230,73 @@ static int parse_iscript_params(char *params, struct polydir_s *poly) + return 0; + } + ++struct mntflag { ++ const char *name; ++ size_t len; ++ unsigned long flag; ++}; ++ ++#define LITERAL_AND_LEN(x) x, sizeof(x) - 1 ++ ++static const struct mntflag mntflags[] = { ++ { LITERAL_AND_LEN("noexec"), MS_NOEXEC }, ++ { LITERAL_AND_LEN("nosuid"), MS_NOSUID }, ++ { LITERAL_AND_LEN("nodev"), MS_NODEV } ++ }; ++ ++static int filter_mntopts(const char *opts, char **filtered, ++ unsigned long *mountflags) ++{ ++ size_t origlen = strlen(opts); ++ const char *end; ++ char *dest; ++ ++ dest = *filtered = NULL; ++ *mountflags = 0; ++ ++ if (origlen == 0) ++ return 0; ++ ++ do { ++ size_t len; ++ int i; ++ ++ end = strchr(opts, ','); ++ if (end == NULL) { ++ len = strlen(opts); ++ } else { ++ len = end - opts; ++ } ++ ++ for (i = 0; i < (int)(sizeof(mntflags)/sizeof(mntflags[0])); i++) { ++ if (mntflags[i].len != len) ++ continue; ++ if (memcmp(mntflags[i].name, opts, len) == 0) { ++ *mountflags |= mntflags[i].flag; ++ opts = end; ++ break; ++ } ++ } ++ ++ if (opts != end) { ++ if (dest != NULL) { ++ *dest = ','; ++ ++dest; ++ } else { ++ dest = *filtered = calloc(1, origlen + 1); ++ if (dest == NULL) ++ return -1; ++ } ++ memcpy(dest, opts, len); ++ dest += len; ++ } ++ ++ opts = end + 1; ++ } while (end != NULL); ++ ++ return 0; ++} ++ + static int parse_method(char *method, struct polydir_s *poly, + struct instance_data *idata) + { +@@ -289,7 +356,8 @@ static int parse_method(char *method, struct polydir_s *poly, + break; + } + free(poly->mount_opts); /* if duplicate mntopts specified */ +- if ((poly->mount_opts = strdup(flag+namelen+1)) == NULL) { ++ poly->mount_opts = NULL; ++ if (filter_mntopts(flag+namelen+1, &poly->mount_opts, &poly->mount_flags) != 0) { + pam_syslog(idata->pamh, LOG_CRIT, "Memory allocation error"); + return -1; + } +@@ -1484,7 +1552,7 @@ static int ns_setup(struct polydir_s *polyptr, + } + + if (polyptr->method == TMPFS) { +- if (mount("tmpfs", polyptr->dir, "tmpfs", 0, polyptr->mount_opts) < 0) { ++ if (mount("tmpfs", polyptr->dir, "tmpfs", polyptr->mount_flags, polyptr->mount_opts) < 0) { + pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m", + polyptr->dir); + return PAM_SESSION_ERR; +diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h +index 47ebcc3..1522386 100644 +--- a/modules/pam_namespace/pam_namespace.h ++++ b/modules/pam_namespace/pam_namespace.h +@@ -166,6 +166,7 @@ struct polydir_s { + unsigned int flags; /* polydir flags */ + char *init_script; /* path to init script */ + char *mount_opts; /* mount options for tmpfs mount */ ++ unsigned long mount_flags; /* mount flags for tmpfs mount */ + uid_t owner; /* user which should own the polydir */ + gid_t group; /* group which should own the polydir */ + mode_t mode; /* mode of the polydir */ diff --git a/SOURCES/pam-1.3.1-namespace-protect-dir.patch b/SOURCES/pam-1.3.1-namespace-protect-dir.patch new file mode 100644 index 0000000..39e2b5e --- /dev/null +++ b/SOURCES/pam-1.3.1-namespace-protect-dir.patch @@ -0,0 +1,58 @@ +From 031bb5a5d0d950253b68138b498dc93be69a64cb Mon Sep 17 00:00:00 2001 +From: Matthias Gerstner +Date: Wed, 27 Dec 2023 14:01:59 +0100 +Subject: [PATCH] pam_namespace: protect_dir(): use O_DIRECTORY to prevent + local DoS situations + +Without O_DIRECTORY the path crawling logic is subject to e.g. FIFOs +being placed in user controlled directories, causing the PAM module to +block indefinitely during `openat()`. + +Pass O_DIRECTORY to cause the `openat()` to fail if the path does not +refer to a directory. + +With this the check whether the final path element is a directory +becomes unnecessary, drop it. +--- + modules/pam_namespace/pam_namespace.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c +index 2528cff8..f72d6718 100644 +--- a/modules/pam_namespace/pam_namespace.c ++++ b/modules/pam_namespace/pam_namespace.c +@@ -1201,7 +1201,7 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir, + int dfd = AT_FDCWD; + int dfd_next; + int save_errno; +- int flags = O_RDONLY; ++ int flags = O_RDONLY | O_DIRECTORY; + int rv = -1; + struct stat st; + +@@ -1255,22 +1255,6 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir, + rv = openat(dfd, dir, flags); + } + +- if (rv != -1) { +- if (fstat(rv, &st) != 0) { +- save_errno = errno; +- close(rv); +- rv = -1; +- errno = save_errno; +- goto error; +- } +- if (!S_ISDIR(st.st_mode)) { +- close(rv); +- errno = ENOTDIR; +- rv = -1; +- goto error; +- } +- } +- + if (flags & O_NOFOLLOW) { + /* we are inside user-owned dir - protect */ + if (protect_mount(rv, p, idata) == -1) { +-- +2.43.0 + diff --git a/SOURCES/pam-1.3.1-noflex.patch b/SOURCES/pam-1.3.1-noflex.patch new file mode 100644 index 0000000..c65d225 --- /dev/null +++ b/SOURCES/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 + # + +-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/SOURCES/pam-1.3.1-pam-cc-compat.patch b/SOURCES/pam-1.3.1-pam-cc-compat.patch new file mode 100644 index 0000000..fe9a95a --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-cc-compat.patch @@ -0,0 +1,63 @@ +diff -up Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.pam-cc-compat Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h +--- Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.pam-cc-compat 2022-05-26 10:43:50.436328027 +0200 ++++ Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h 2022-05-26 10:43:50.436328027 +0200 +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (c) 2020 Dmitry V. Levin ++ */ ++ ++#ifndef PAM_CC_COMPAT_H ++#define PAM_CC_COMPAT_H ++ ++#include "config.h" ++#include ++ ++#if defined __clang__ && defined __clang_major__ && defined __clang_minor__ ++# define PAM_CLANG_PREREQ(maj, min) \ ++ ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) ++#else ++# define PAM_CLANG_PREREQ(maj, min) 0 ++#endif ++ ++#if PAM_GNUC_PREREQ(4, 6) ++# define DIAG_PUSH_IGNORE_CAST_QUAL \ ++ _Pragma("GCC diagnostic push"); \ ++ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") ++# define DIAG_POP_IGNORE_CAST_QUAL \ ++ _Pragma("GCC diagnostic pop") ++# define DIAG_PUSH_IGNORE_CAST_ALIGN \ ++ _Pragma("GCC diagnostic push"); \ ++ _Pragma("GCC diagnostic ignored \"-Wcast-align\"") ++# define DIAG_POP_IGNORE_CAST_ALIGN \ ++ _Pragma("GCC diagnostic pop") ++#elif PAM_CLANG_PREREQ(2, 6) ++# define DIAG_PUSH_IGNORE_CAST_QUAL \ ++ _Pragma("clang diagnostic push"); \ ++ _Pragma("clang diagnostic ignored \"-Wcast-qual\"") ++# define DIAG_POP_IGNORE_CAST_QUAL \ ++ _Pragma("clang diagnostic pop") ++# define DIAG_PUSH_IGNORE_CAST_ALIGN \ ++ _Pragma("clang diagnostic push"); \ ++ _Pragma("clang diagnostic ignored \"-Wcast-align\"") ++# define DIAG_POP_IGNORE_CAST_ALIGN \ ++ _Pragma("clang diagnostic pop") ++#else ++# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */ ++# define DIAG_POP_IGNORE_CAST_QUAL /* empty */ ++# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */ ++# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */ ++#endif ++ ++#endif /* PAM_CC_COMPAT_H */ +diff -up Linux-PAM-1.3.1/libpam/Makefile.am.pam-cc-compat Linux-PAM-1.3.1/libpam/Makefile.am +--- Linux-PAM-1.3.1/libpam/Makefile.am.pam-cc-compat 2022-05-26 10:43:50.436328027 +0200 ++++ Linux-PAM-1.3.1/libpam/Makefile.am 2022-05-26 10:44:00.865402730 +0200 +@@ -18,7 +18,7 @@ include_HEADERS = include/security/_pam_ + include/security/pam_ext.h include/security/pam_modutil.h + + noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \ +- pam_modutil_private.h ++ pam_modutil_private.h include/pam_cc_compat.h + + libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84 + libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@ diff --git a/SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch b/SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch new file mode 100644 index 0000000..1f322a1 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch @@ -0,0 +1,125 @@ +diff -up Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c +--- Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c 2022-04-25 12:10:28.071240439 +0200 +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #define KEY_SPEC_SESSION_KEYRING -3 /* ID for session keyring */ + #define KEY_SPEC_USER_KEYRING -4 /* ID for UID-specific keyring */ +@@ -30,12 +31,12 @@ + #define KEYCTL_REVOKE 3 /* revoke a key */ + #define KEYCTL_LINK 8 /* link a key into a keyring */ + +-static int my_session_keyring; +-static int session_counter; +-static int do_revoke; +-static int revoke_as_uid; +-static int revoke_as_gid; +-static int xdebug = 0; ++static _Thread_local int my_session_keyring = 0; ++static _Atomic int session_counter = 0; ++static _Thread_local int do_revoke = 0; ++static _Thread_local uid_t revoke_as_uid; ++static _Thread_local gid_t revoke_as_gid; ++static _Thread_local int xdebug = 0; + + static void debug(pam_handle_t *pamh, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +@@ -65,6 +66,33 @@ static int error(pam_handle_t *pamh, con + return PAM_SESSION_ERR; + } + ++static int pam_setreuid(uid_t ruid, uid_t euid) ++{ ++#if defined(SYS_setreuid32) ++ return syscall(SYS_setreuid32, ruid, euid); ++#else ++ return syscall(SYS_setreuid, ruid, euid); ++#endif ++} ++ ++static int pam_setregid(gid_t rgid, gid_t egid) ++{ ++#if defined(SYS_setregid32) ++ return syscall(SYS_setregid32, rgid, egid); ++#else ++ return syscall(SYS_setregid, rgid, egid); ++#endif ++} ++ ++static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid) ++{ ++#if defined(SYS_setresuid32) ++ return syscall(SYS_setresuid32, ruid, euid, suid); ++#else ++ return syscall(SYS_setresuid, ruid, euid, suid); ++#endif ++} ++ + /* + * initialise the session keyring for this process + */ +@@ -139,23 +167,25 @@ static void kill_keyrings(pam_handle_t * + + /* switch to the real UID and GID so that we have permission to + * revoke the key */ +- if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0) ++ if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0) + error(pamh, "Unable to change GID to %d temporarily\n", + revoke_as_gid); + +- if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0) ++ if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0) + error(pamh, "Unable to change UID to %d temporarily\n", + revoke_as_uid); ++ if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0) ++ error(pamh, "Unable to change GID back to %d\n", old_gid); + + syscall(__NR_keyctl, + KEYCTL_REVOKE, + my_session_keyring); + + /* return to the orignal UID and GID (probably root) */ +- if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0) ++ if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0) + error(pamh, "Unable to change UID back to %d\n", old_uid); + +- if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0) ++ if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0) + error(pamh, "Unable to change GID back to %d\n", old_gid); + + my_session_keyring = 0; +@@ -210,14 +240,14 @@ int pam_sm_open_session(pam_handle_t *pa + + /* switch to the real UID and GID so that the keyring ends up owned by + * the right user */ +- if (gid != old_gid && setregid(gid, -1) < 0) { ++ if (gid != old_gid && pam_setregid(gid, -1) < 0) { + error(pamh, "Unable to change GID to %d temporarily\n", gid); + return PAM_SESSION_ERR; + } + +- if (uid != old_uid && setreuid(uid, -1) < 0) { ++ if (uid != old_uid && pam_setreuid(uid, -1) < 0) { + error(pamh, "Unable to change UID to %d temporarily\n", uid); +- if (setregid(old_gid, -1) < 0) ++ if (pam_setregid(old_gid, -1) < 0) + error(pamh, "Unable to change GID back to %d\n", old_gid); + return PAM_SESSION_ERR; + } +@@ -225,10 +255,10 @@ int pam_sm_open_session(pam_handle_t *pa + ret = init_keyrings(pamh, force); + + /* return to the orignal UID and GID (probably root) */ +- if (uid != old_uid && setreuid(old_uid, -1) < 0) ++ if (uid != old_uid && pam_setreuid(old_uid, -1) < 0) + ret = error(pamh, "Unable to change UID back to %d\n", old_uid); + +- if (gid != old_gid && setregid(old_gid, -1) < 0) ++ if (gid != old_gid && pam_setregid(old_gid, -1) < 0) + ret = error(pamh, "Unable to change GID back to %d\n", old_gid); + + return ret; diff --git a/SOURCES/pam-1.3.1-pam-limits-unlimited-value.patch b/SOURCES/pam-1.3.1-pam-limits-unlimited-value.patch new file mode 100644 index 0000000..1cf063c --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-limits-unlimited-value.patch @@ -0,0 +1,78 @@ +diff -up Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml.pam-limits-unlimited-value Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml +--- Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml.pam-limits-unlimited-value 2022-01-28 09:45:41.431606850 +0100 ++++ Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml 2022-01-28 09:47:31.732430391 +0100 +@@ -275,6 +275,8 @@ + All items support the values -1, + unlimited or infinity indicating no limit, + except for priority and nice. ++ If nofile is to be set to one of these values, ++ it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)). + + + If a hard limit or soft limit of a resource is set to a valid value, +diff -up Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c.pam-limits-unlimited-value Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c +--- Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c.pam-limits-unlimited-value 2022-01-28 09:45:41.415606731 +0100 ++++ Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c 2022-01-28 09:45:41.431606850 +0100 +@@ -487,6 +487,41 @@ static int init_limits(pam_handle_t *pam + return retval; + } + ++/* ++ * Read the contents of and return it in *valuep ++ * return 1 if conversion succeeds, result is in *valuep ++ * return 0 if conversion fails, *valuep is untouched. ++ */ ++static int ++value_from_file(const char *pathname, rlim_t *valuep) ++{ ++ char buf[128]; ++ FILE *fp; ++ int retval; ++ ++ retval = 0; ++ ++ if ((fp = fopen(pathname, "r")) != NULL) { ++ if (fgets(buf, sizeof(buf), fp) != NULL) { ++ char *endptr; ++ unsigned long long value; ++ ++ errno = 0; ++ value = strtoull(buf, &endptr, 10); ++ if (endptr != buf && ++ (value != ULLONG_MAX || errno == 0) && ++ (unsigned long long) (rlim_t) value == value) { ++ *valuep = (rlim_t) value; ++ retval = 1; ++ } ++ } ++ ++ fclose(fp); ++ } ++ ++ return retval; ++} ++ + static void + process_limit (const pam_handle_t *pamh, int source, const char *lim_type, + const char *lim_item, const char *lim_value, +@@ -652,6 +687,20 @@ process_limit (const pam_handle_t *pamh, + rlimit_value = 20 - int_value; + break; + #endif ++ case RLIMIT_NOFILE: ++ /* ++ * If nofile is to be set to "unlimited", try to set it to ++ * the value in /proc/sys/fs/nr_open instead. ++ */ ++ if (rlimit_value == RLIM_INFINITY) { ++ if (!value_from_file("/proc/sys/fs/nr_open", &rlimit_value)) ++ pam_syslog(pamh, LOG_WARNING, ++ "Cannot set \"nofile\" to a sensible value"); ++ else if (ctrl & PAM_DEBUG_ARG) ++ pam_syslog(pamh, LOG_DEBUG, "Setting \"nofile\" limit to %llu", ++ (unsigned long long) rlimit_value); ++ } ++ break; + } + + if ( (limit_item != LIMIT_LOGIN) diff --git a/SOURCES/pam-1.3.1-pam-misc-configurable.patch b/SOURCES/pam-1.3.1-pam-misc-configurable.patch new file mode 100644 index 0000000..045e70e --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-misc-configurable.patch @@ -0,0 +1,29 @@ +diff -up Linux-PAM-1.3.1/configure.ac.pam-misc-configurable Linux-PAM-1.3.1/configure.ac +--- Linux-PAM-1.3.1/configure.ac.pam-misc-configurable 2023-06-26 09:57:00.243146563 +0200 ++++ Linux-PAM-1.3.1/configure.ac 2023-06-26 09:59:45.353636685 +0200 +@@ -621,6 +621,13 @@ if test x"$opt_kerneloverflowuid" == x; + fi + AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.]) + ++AC_ARG_WITH([misc-conv-bufsize], ++AS_HELP_STRING([--with-misc-conv-bufsize=], ++ [Size of input buffer for libpam_misc's misc_conv() conversation function, default=4096]), ++ [], ++ [with_misc_conv_bufsize=4096]) ++AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.]) ++ + dnl Files to be created from when we run configure + AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \ + libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \ +diff -up Linux-PAM-1.3.1/libpam_misc/misc_conv.c.pam-misc-configurable Linux-PAM-1.3.1/libpam_misc/misc_conv.c +--- Linux-PAM-1.3.1/libpam_misc/misc_conv.c.pam-misc-configurable 2023-06-26 09:57:00.242146560 +0200 ++++ Linux-PAM-1.3.1/libpam_misc/misc_conv.c 2023-06-26 10:00:38.023787972 +0200 +@@ -18,7 +18,7 @@ + #include + #include + +-#define INPUTSIZE PAM_MAX_MSG_SIZE /* maximum length of input+1 */ ++#define INPUTSIZE PAM_MISC_CONV_BUFSIZE /* maximum length of input+1 */ + #define CONV_ECHO_ON 1 /* types of echo state */ + #define CONV_ECHO_OFF 0 + diff --git a/SOURCES/pam-1.3.1-pam-modutil-close-write.patch b/SOURCES/pam-1.3.1-pam-modutil-close-write.patch new file mode 100644 index 0000000..611e855 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-modutil-close-write.patch @@ -0,0 +1,74 @@ +From b6f73810a2e7afd02a231e2dfa14b05752c83db7 Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Wed, 26 Feb 2020 19:20:58 +0000 +Subject: [PATCH] pam_modutil_sanitize_helper_fds: fix SIGPIPE effect of + PAM_MODUTIL_PIPE_FD + +When pam_modutil_sanitize_helper_fds() is invoked with +PAM_MODUTIL_PIPE_FD to provide a dummy pipe descriptor for stdout +or stderr, it closes the read end of the newly created dummy pipe. +The negative side effect of this approach is that any write to such +descriptor triggers a SIGPIPE. Avoid this by closing the write end of +the dummy pipe and using its read end as a dummy pipe descriptor for +output. Any read from such descriptor returns 0, and any write just +fails with EBADF, which should work better with unprepared writers. + +* libpam/pam_modutil_sanitize.c (redirect_out_pipe): Remove. +(redirect_out): Call redirect_in_pipe instead of redirect_out_pipe. + +Fixes: b0ec5d1e ("Introduce pam_modutil_sanitize_helper_fds") +--- + libpam/pam_modutil_sanitize.c | 30 +----------------------------- + 1 file changed, 1 insertion(+), 29 deletions(-) + +diff --git a/libpam/pam_modutil_sanitize.c b/libpam/pam_modutil_sanitize.c +index 605c859d..58b9537c 100644 +--- a/libpam/pam_modutil_sanitize.c ++++ b/libpam/pam_modutil_sanitize.c +@@ -46,34 +46,6 @@ redirect_in_pipe(pam_handle_t *pamh, int fd, const char *name) + return fd; + } + +-/* +- * Creates a pipe, closes its read end, redirects fd to its write end. +- * Returns fd on success, -1 otherwise. +- */ +-static int +-redirect_out_pipe(pam_handle_t *pamh, int fd, const char *name) +-{ +- int out[2]; +- +- if (pipe(out) < 0) { +- pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m"); +- return -1; +- } +- +- close(out[0]); +- +- if (out[1] == fd) +- return fd; +- +- if (dup2(out[1], fd) != fd) { +- pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", name); +- fd = -1; +- } +- +- close(out[1]); +- return fd; +-} +- + /* + * Opens /dev/null for writing, redirects fd there. + * Returns fd on success, -1 otherwise. +@@ -106,7 +78,7 @@ redirect_out(pam_handle_t *pamh, enum pam_modutil_redirect_fd mode, + { + switch (mode) { + case PAM_MODUTIL_PIPE_FD: +- if (redirect_out_pipe(pamh, fd, name) < 0) ++ if (redirect_in_pipe(pamh, fd, name) < 0) + return -1; + break; + case PAM_MODUTIL_NULL_FD: +-- +2.25.3 + diff --git a/SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch b/SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch new file mode 100644 index 0000000..52f7292 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch @@ -0,0 +1,283 @@ +From d57ab22133654033ee1da89f128a81572d320985 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Thu, 20 Dec 2018 13:59:25 +0100 +Subject: [PATCH] pam_motd: Cleanup the code and avoid unnecessary logging + +The pam_motd module will not log if the default motd.d directories +are missing. + +Also cleanup some code cleanliness issues and fix compilation +warnings. + +* modules/pam_motd/pam_motd.c: Constification of constant strings. + (try_to_display_directory): Removed unused function. + (pam_split_string): Replace uint with unsigned int. Fix warnings. + (compare_strings): Fix warnings by proper constification. + (try_to_display_directories_with_overrides): Cleanups. Switch + off the logging if the motd.d directories are missing and they + are default ones. + (pam_sm_open_session): Cleanup warnings. Pass the information + to try_to_display_directories_with_overrides() that non-default + motd options are used. +--- + modules/pam_motd/pam_motd.c | 88 ++++++++++++++++--------------------- + 1 file changed, 37 insertions(+), 51 deletions(-) + +diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c +index ec3ebd58..dbd718b6 100644 +--- a/modules/pam_motd/pam_motd.c ++++ b/modules/pam_motd/pam_motd.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -48,8 +49,8 @@ pam_sm_close_session (pam_handle_t *pamh UNUSED, int flags UNUSED, + return PAM_IGNORE; + } + +-static char default_motd[] = DEFAULT_MOTD; +-static char default_motd_dir[] = DEFAULT_MOTD_D; ++static const char default_motd[] = DEFAULT_MOTD; ++static const char default_motd_dir[] = DEFAULT_MOTD_D; + + static void try_to_display_fd(pam_handle_t *pamh, int fd) + { +@@ -75,28 +76,6 @@ static void try_to_display_fd(pam_handle_t *pamh, int fd) + _pam_drop(mtmp); + } + +-static void try_to_display_directory(pam_handle_t *pamh, const char *dirname) +-{ +- DIR *dirp; +- +- dirp = opendir(dirname); +- +- if (dirp != NULL) { +- struct dirent *entry; +- +- while ((entry = readdir(dirp))) { +- int fd = openat(dirfd(dirp), entry->d_name, O_RDONLY); +- +- if (fd >= 0) { +- try_to_display_fd(pamh, fd); +- close(fd); +- } +- } +- +- closedir(dirp); +- } +-} +- + /* + * Split a DELIM-separated string ARG into an array. + * Outputs a newly allocated array of strings OUT_ARG_SPLIT +@@ -104,14 +83,14 @@ static void try_to_display_directory(pam_handle_t *pamh, const char *dirname) + * 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 ***out_arg_split, unsigned int *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; ++ unsigned int i = 0; ++ unsigned int num_strs = 0; + int retval = 0; + + delim_str[0] = delim; +@@ -126,7 +105,7 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim, + arg_ptr = strchr(arg_ptr + sizeof(const char), delim); + } + +- arg_split = (char **)calloc(num_strs, sizeof(char *)); ++ arg_split = calloc(num_strs, sizeof(char *)); + if (arg_split == NULL) { + pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate string array"); + goto out; +@@ -180,10 +159,10 @@ static int join_dir_strings(char **strp_out, const char *a_str, const char *b_st + return retval; + } + +-static int compare_strings(const void * a, const void * b) ++static int compare_strings(const void *a, const void *b) + { +- const char *a_str = *(char **)a; +- const char *b_str = *(char **)b; ++ const char *a_str = *(const char * const *)a; ++ const char *b_str = *(const char * const *)b; + + if (a_str == NULL && b_str == NULL) { + return 0; +@@ -205,13 +184,13 @@ static int filter_dirents(const struct dirent *d) + } + + static void try_to_display_directories_with_overrides(pam_handle_t *pamh, +- char **motd_dir_path_split, int num_motd_dirs) ++ char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing) + { + struct dirent ***dirscans = NULL; +- int *dirscans_sizes = NULL; +- int dirscans_size_total = 0; ++ unsigned int *dirscans_sizes = NULL; ++ unsigned int dirscans_size_total = 0; + char **dirnames_all = NULL; +- int i; ++ unsigned int i; + int i_dirnames = 0; + + if (pamh == NULL || motd_dir_path_split == NULL) { +@@ -221,29 +200,31 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + goto out; + } + +- if ((dirscans = (struct dirent ***)calloc(num_motd_dirs, +- sizeof(struct dirent **))) == NULL) { ++ if ((dirscans = 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) { ++ if ((dirscans_sizes = 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]), ++ int rv; ++ rv = 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; ++ if (rv < 0) { ++ if (errno != ENOENT || report_missing) { ++ pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s: %m", ++ motd_dir_path_split[i]); ++ } ++ dirscans_sizes[i] = rv; + } + 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) { ++ if ((dirnames_all = calloc(dirscans_size_total, sizeof(char *))) == NULL) { + pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array"); + goto out; + } +@@ -253,7 +234,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + } + + for (i = 0; i < num_motd_dirs; i++) { +- int j; ++ unsigned int j; + + for (j = 0; j < dirscans_sizes[i]; j++) { + dirnames_all[i_dirnames] = dirscans[i][j]->d_name; +@@ -265,7 +246,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + sizeof(const char *), compare_strings); + + for (i = 0; i < dirscans_size_total; i++) { +- int j; ++ unsigned int j; + + if (dirnames_all[i] == NULL) { + continue; +@@ -301,7 +282,8 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + out: + _pam_drop(dirnames_all); + for (i = 0; i < num_motd_dirs; i++) { +- int j; ++ unsigned int j; ++ + for (j = 0; j < dirscans_sizes[i]; j++) { + _pam_drop(dirscans[i][j]); + } +@@ -319,12 +301,13 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, + int retval = PAM_IGNORE; + const char *motd_path = NULL; + char *motd_path_copy = NULL; +- int num_motd_paths = 0; ++ unsigned 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; ++ unsigned int num_motd_dir_paths = 0; + char **motd_dir_path_split = NULL; ++ int report_missing; + + if (flags & PAM_SILENT) { + return retval; +@@ -360,6 +343,9 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, + if (motd_path == NULL && motd_dir_path == NULL) { + motd_path = default_motd; + motd_dir_path = default_motd_dir; ++ report_missing = 0; ++ } else { ++ report_missing = 1; + } + + if (motd_path != NULL) { +@@ -385,7 +371,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, + } + + if (motd_path_split != NULL) { +- int i; ++ unsigned int i; + + for (i = 0; i < num_motd_paths; i++) { + int fd = open(motd_path_split[i], O_RDONLY, 0); +@@ -402,7 +388,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, + + if (motd_dir_path_split != NULL) + try_to_display_directories_with_overrides(pamh, motd_dir_path_split, +- num_motd_dir_paths); ++ num_motd_dir_paths, report_missing); + + out: + _pam_drop(motd_path_copy); +-- +2.37.3 + +From c2c0434bd634a817f2b16ce7f58fc96c04e88b03 Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Sun, 26 Apr 2020 11:12:59 +0000 +Subject: [PATCH] pam_motd: fix NULL dereference when at least one of motd + directories is not available + +* modules/pam_motd/pam_motd.c +(try_to_display_directories_with_overrides): Do not assign -1U to +dirscans_sizes[i] when scandir(motd_dir_path_split[i]) returns an error. + +Resolves: https://bugzilla.altlinux.org/38389 +Fixes: d57ab221 ("pam_motd: Cleanup the code and avoid unnecessary logging") +--- + modules/pam_motd/pam_motd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c +index df09b7d0..8147c6fd 100644 +--- a/modules/pam_motd/pam_motd.c ++++ b/modules/pam_motd/pam_motd.c +@@ -219,6 +219,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s: %m", + motd_dir_path_split[i]); + } ++ } else { + dirscans_sizes[i] = rv; + } + dirscans_size_total += dirscans_sizes[i]; +-- +2.37.3 + diff --git a/SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch b/SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch new file mode 100644 index 0000000..932633b --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch @@ -0,0 +1,57 @@ +From 62cd745d730e5ba13d5d7092ac566fc0b2148e61 Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Sun, 26 Apr 2020 11:12:59 +0000 +Subject: [PATCH] pam_motd: fix memory leak + +pam_motd used to leak memory allocated for each motd file +successfully opened in try_to_display_directories_with_overrides. + +* modules/pam_motd/pam_motd.c +(try_to_display_directories_with_overrides): Free abs_path. + +Fixes: f9c9c721 ("pam_motd: Support multiple motd paths specified, with filename overrides (#69)") +--- + modules/pam_motd/pam_motd.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c +index f0cd317d..3be129a5 100644 +--- a/modules/pam_motd/pam_motd.c ++++ b/modules/pam_motd/pam_motd.c +@@ -259,23 +259,23 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + + for (j = 0; j < num_motd_dirs; j++) { + char *abs_path = NULL; ++ int fd; + + if (join_dir_strings(&abs_path, motd_dir_path_split[j], +- dirnames_all[i]) < 0) { ++ dirnames_all[i]) < 0 || abs_path == NULL) { + continue; + } + +- if (abs_path != NULL) { +- int fd = open(abs_path, O_RDONLY, 0); +- if (fd >= 0) { +- try_to_display_fd(pamh, fd); +- close(fd); ++ fd = open(abs_path, O_RDONLY, 0); ++ _pam_drop(abs_path); + +- /* We displayed a file, skip to the next file name. */ +- break; +- } ++ 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); + } + } + +-- +2.35.3 + diff --git a/SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch b/SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch new file mode 100644 index 0000000..af72866 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch @@ -0,0 +1,133 @@ +From 8eaf5570cf011148a0b55c53570df5edaafebdb0 Mon Sep 17 00:00:00 2001 +From: Robert Fairley +Date: Wed, 21 Nov 2018 02:46:02 -0500 +Subject: [PATCH] pam_motd: Fix segmentation fault when no motd_dir specified + (#76) + +This fixes a regression introduced by #69, where motd_path was set +to NULL and passed into strdup() if the motd_dir argument was +not specified in the configuration file. This caused a segmentation +fault. + +* modules/pam_motd/pam_motd.c: fix checks for NULL in arguments +* xtests/Makefile.am: add test scripts and config file +* xtests/tst-pam_motd.sh: add running tst-pam_motd4.sh +* xtests/tst-pam_motd4.pamd: create +* xtests/tst-pam_motd4.sh: create +--- + modules/pam_motd/pam_motd.c | 15 ++++++++++----- + xtests/Makefile.am | 4 ++-- + xtests/tst-pam_motd.sh | 1 + + xtests/tst-pam_motd4.pamd | 3 +++ + xtests/tst-pam_motd4.sh | 27 +++++++++++++++++++++++++++ + 5 files changed, 43 insertions(+), 7 deletions(-) + create mode 100644 xtests/tst-pam_motd4.pamd + create mode 100755 xtests/tst-pam_motd4.sh + +diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c +index 1c1cfcfa..ec3ebd58 100644 +--- a/modules/pam_motd/pam_motd.c ++++ b/modules/pam_motd/pam_motd.c +@@ -132,7 +132,6 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim, + goto out; + } + +- + arg_extracted = strtok_r(arg, delim_str, &arg); + while (arg_extracted != NULL && i < num_strs) { + arg_split[i++] = arg_extracted; +@@ -363,15 +362,21 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, + motd_dir_path = default_motd_dir; + } + +- motd_path_copy = strdup(motd_path); ++ if (motd_path != NULL) { ++ 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) { ++ if (pam_split_string(pamh, motd_path_copy, ':', ++ &motd_path_split, &num_motd_paths) == 0) { + goto out; + } + } + +- motd_dir_path_copy = strdup(motd_dir_path); ++ if (motd_dir_path != NULL) { ++ motd_dir_path_copy = strdup(motd_dir_path); ++ } ++ + if (motd_dir_path_copy != NULL) { + if (pam_split_string(pamh, motd_dir_path_copy, ':', + &motd_dir_path_split, &num_motd_dir_paths) == 0) { +diff --git a/xtests/Makefile.am b/xtests/Makefile.am +index 555d5e33..4d5aba3d 100644 +--- a/xtests/Makefile.am ++++ b/xtests/Makefile.am +@@ -34,8 +34,8 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \ + tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \ + tst-pam_time1.pamd time.conf \ + tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \ +- tst-pam_motd3.sh tst-pam_motd1.pamd \ +- tst-pam_motd2.pamd tst-pam_motd3.pamd ++ 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 \ +diff --git a/xtests/tst-pam_motd.sh b/xtests/tst-pam_motd.sh +index 9b0c38f6..90801280 100755 +--- a/xtests/tst-pam_motd.sh ++++ b/xtests/tst-pam_motd.sh +@@ -5,3 +5,4 @@ set -e + ./tst-pam_motd1.sh + ./tst-pam_motd2.sh + ./tst-pam_motd3.sh ++./tst-pam_motd4.sh +diff --git a/xtests/tst-pam_motd4.pamd b/xtests/tst-pam_motd4.pamd +new file mode 100644 +index 00000000..9dc311ad +--- /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 00000000..6022177f +--- /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 +-- +2.35.1 + diff --git a/SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch b/SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch new file mode 100644 index 0000000..f81ecbe --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch @@ -0,0 +1,691 @@ +diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml +--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.939663167 +0200 ++++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml 2022-04-25 12:34:43.506582206 +0200 +@@ -21,6 +21,9 @@ + + motd=/path/filename + ++ ++ motd_dir=/path/dirname.d ++ + + + +@@ -31,18 +34,49 @@ + + 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 /etc/motd file and +- all files from /etc/motd.d are +- shown. The message size is limited to 64KB. ++ login. By default, pam_motd shows files in the ++ following locations: ++ ++ ++ ++ /etc/motd ++ /run/motd ++ /usr/lib/motd ++ /etc/motd.d/ ++ /run/motd.d/ ++ /usr/lib/motd.d/ ++ ++ ++ ++ Each message size is limited to 64KB. ++ ++ ++ If /etc/motd does not exist, ++ then /run/motd is shown. If ++ /run/motd does not exist, then ++ /usr/lib/motd is shown. ++ ++ ++ Similar overriding behavior applies to the directories. ++ Files in /etc/motd.d/ override files ++ with the same name in /run/motd.d/ and ++ /usr/lib/motd.d/. Files in /run/motd.d/ ++ override files with the same name in /usr/lib/motd.d/. ++ ++ ++ Files in the directories listed above are displayed in lexicographic ++ order by name. Moreover, the files are filtered by reading them with the ++ credentials of the target user authenticating on the system. + + + To silence a message, + a symbolic link with target /dev/null + may be placed in /etc/motd.d with + the same filename as the message to be silenced. Example: ++ Creating a symbolic link as follows silences /usr/lib/motd.d/my_motd. + + +- ln -sfn /dev/null /etc/motd.d/my_motd ++ ln -s /dev/null /etc/motd.d/my_motd + + + +@@ -56,8 +90,10 @@ + + + +- The /path/filename file is displayed +- as message of the day. ++ The /path/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 /etc/motd:/run/motd:/usr/lib/motd. + + + +@@ -68,16 +104,17 @@ + + + The /path/dirname.d 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 /etc/motd.d:/run/motd.d:/usr/lib/motd.d. + + + + + +- When no options are given, the default is to display both +- /etc/motd and the contents of +- /etc/motd.d. 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. + + + +diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c +--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 2018-05-18 11:50:46.000000000 +0200 ++++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c 2022-04-25 12:32:36.947663225 +0200 +@@ -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 + #include +@@ -97,12 +97,235 @@ static void try_to_display_directory(pam + } + } + ++/* ++ * 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; +@@ -140,17 +363,47 @@ int pam_sm_open_session(pam_handle_t *pa + motd_dir_path = default_motd_dir; + } + +- 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; ++ } ++ } ++ ++ motd_dir_path_copy = strdup(motd_dir_path); ++ 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_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); ++ 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 != NULL) +- try_to_display_directory(pamh, motd_dir_path); ++ 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 -up Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/Makefile.am +--- Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/xtests/Makefile.am 2022-04-25 12:32:36.947663225 +0200 +@@ -32,7 +32,10 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispa + 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_motd1.pamd \ ++ tst-pam_motd2.pamd tst-pam_motd3.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_dispa + 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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd +--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd 2022-04-25 12:32:36.947663225 +0200 +@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh +--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh 2022-04-25 12:32:36.947663225 +0200 +@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd +--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd 2022-04-25 12:32:36.947663225 +0200 +@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh +--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh 2022-04-25 12:32:36.947663225 +0200 +@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd +--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd 2022-04-25 12:32:36.947663225 +0200 +@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh +--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh 2022-04-25 12:32:36.947663225 +0200 +@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.c +--- Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd.c 2022-04-25 12:32:36.947663225 +0200 +@@ -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 ++#endif ++ ++#include ++#include ++#include ++#include ++ ++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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.sh +--- Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200 ++++ Linux-PAM-1.3.1/xtests/tst-pam_motd.sh 2022-04-25 12:32:36.947663225 +0200 +@@ -0,0 +1,7 @@ ++#!/bin/bash ++ ++set -e ++ ++./tst-pam_motd1.sh ++./tst-pam_motd2.sh ++./tst-pam_motd3.sh diff --git a/SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch b/SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch new file mode 100644 index 0000000..35e3d94 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch @@ -0,0 +1,573 @@ +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am +--- Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.709355179 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am 2022-09-29 10:13:35.780355766 +0200 +@@ -10,9 +10,10 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst- + + TESTS = tst-pam_pwhistory + +-man_MANS = pam_pwhistory.8 pwhistory_helper.8 ++man_MANS = pam_pwhistory.8 pwhistory_helper.8 pwhistory.conf.5 + +-XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml ++XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml \ ++ pwhistory.conf.5.xml + + securelibdir = $(SECUREDIR) + secureconfdir = $(SCONFIGDIR) +@@ -25,12 +26,14 @@ if HAVE_VERSIONING + pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map + endif + +-noinst_HEADERS = opasswd.h ++noinst_HEADERS = opasswd.h pwhistory_config.h ++ ++dist_secureconf_DATA = pwhistory.conf + + securelib_LTLIBRARIES = pam_pwhistory.la + 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 ++pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c pwhistory_config.c + + sbin_PROGRAMS = pwhistory_helper + pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@ +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml +--- Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml 2022-09-29 10:13:35.780355766 +0200 +@@ -36,6 +36,9 @@ + + authtok_type=STRING + ++ ++ conf=/path/to/config-file ++ + + + +@@ -104,7 +107,7 @@ + + + The last N passwords for each +- user are saved in /etc/security/opasswd. ++ user are saved. + The default is 10. Value of + 0 makes the module to keep the existing + contents of the opasswd file unchanged. +@@ -137,7 +140,26 @@ + + + ++ ++ ++ ++ ++ ++ ++ Use another configuration file instead of the default ++ /etc/security/pwhistory.conf. ++ ++ ++ ++ + ++ ++ The options for configuring the module behavior are described in the ++ pwhistory.conf ++ 5 manual page. The options ++ specified on the module command line override the values from the ++ configuration file. ++ + + + +@@ -223,6 +245,9 @@ password required pam_unix.so + SEE ALSO + + ++ pwhistory.conf5 ++ , ++ + pam.conf5 + , + +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c +--- Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.711355195 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c 2022-09-29 10:13:35.780355766 +0200 +@@ -62,18 +62,11 @@ + #include + + #include "opasswd.h" ++#include "pwhistory_config.h" + + #define DEFAULT_BUFLEN 2048 + #define MAX_FD_NO 20000 + +-struct options_t { +- int debug; +- int enforce_for_root; +- int remember; +- int tries; +-}; +-typedef struct options_t options_t; +- + + static void + parse_option (pam_handle_t *pamh, const char *argv, options_t *options) +@@ -304,6 +297,8 @@ pam_sm_chauthtok (pam_handle_t *pamh, in + options.remember = 10; + options.tries = 1; + ++ parse_config_file(pamh, argc, argv, &options); ++ + /* Parse parameters for module */ + for ( ; argc-- > 0; argv++) + parse_option (pamh, *argv, &options); +@@ -311,7 +306,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, in + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok entered"); + +- + if (options.remember == 0) + return PAM_IGNORE; + +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml +--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.780355766 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml 2022-09-29 10:13:35.780355766 +0200 +@@ -0,0 +1,155 @@ ++ ++ ++ ++ ++ ++ ++ pwhistory.conf ++ 5 ++ Linux-PAM Manual ++ ++ ++ ++ pwhistory.conf ++ pam_pwhistory configuration file ++ ++ ++ ++ ++ DESCRIPTION ++ ++ pwhistory.conf provides a way to configure the ++ default settings for saving the last passwords for each user. ++ This file is read by the pam_pwhistory module and is the ++ preferred method over configuring pam_pwhistory directly. ++ ++ ++ The file has a very simple name = value format with possible comments ++ starting with # character. The whitespace at the beginning of line, end ++ of line, and around the = sign is ignored. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ Turns on debugging via ++ ++ syslog3 ++ . ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ If this option is set, the check is enforced for root, too. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The last N passwords for each ++ user are saved. ++ The default is 10. Value of ++ 0 makes the module to keep the existing ++ contents of the opasswd file unchanged. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Prompt user at most N times ++ before returning with error. The default is 1. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Store password history in file ++ /path/filename rather than the default ++ location. The default location is ++ /etc/security/opasswd. ++ ++ ++ ++ ++ ++ ++ ++ EXAMPLES ++ ++ /etc/security/pwhistory.conf file example: ++ ++ ++debug ++remember=5 ++file=/tmp/opasswd ++ ++ ++ ++ ++ FILES ++ ++ ++ /etc/security/pwhistory.conf ++ ++ the config file for custom options ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ pwhistory8 ++ , ++ ++ pam_pwhistory8 ++ , ++ ++ pam.conf5 ++ , ++ ++ pam.d5 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ pam_pwhistory was written by Thorsten Kukuk. The support for ++ pwhistory.conf was written by Iker Pedrosa. ++ ++ ++ ++ +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c +--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.781355775 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c 2022-09-29 10:14:33.377832622 +0200 +@@ -0,0 +1,195 @@ ++/* ++ * Copyright (c) 2022 Iker Pedrosa ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "pam_inline.h" ++#include "pwhistory_config.h" ++ ++#define PWHISTORY_DEFAULT_CONF "/etc/security/pwhistory.conf" ++ ++/* lookup a value for key in login.defs file or similar key value format */ ++static char * ++pwhistory_search_key(pam_handle_t *pamh UNUSED, ++ const char *file_name, ++ const char *key) ++{ ++ FILE *fp; ++ char *buf = NULL; ++ size_t buflen = 0; ++ char *retval = NULL; ++ ++#ifdef USE_ECONF ++ if (strcmp (file_name, LOGIN_DEFS) == 0) ++ return econf_search_key ("login", ".defs", key); ++#endif ++ ++ fp = fopen(file_name, "r"); ++ if (NULL == fp) ++ return NULL; ++ ++ while (!feof(fp)) { ++ char *tmp, *cp; ++#if defined(HAVE_GETLINE) ++ ssize_t n = getline(&buf, &buflen, fp); ++#elif defined (HAVE_GETDELIM) ++ ssize_t n = getdelim(&buf, &buflen, '\n', fp); ++#else ++ ssize_t n; ++ ++ if (buf == NULL) { ++ buflen = BUF_SIZE; ++ buf = malloc(buflen); ++ if (buf == NULL) { ++ fclose(fp); ++ return NULL; ++ } ++ } ++ buf[0] = '\0'; ++ if (fgets(buf, buflen - 1, fp) == NULL) ++ break; ++ else if (buf != NULL) ++ n = strlen(buf); ++ else ++ n = 0; ++#endif /* HAVE_GETLINE / HAVE_GETDELIM */ ++ cp = buf; ++ ++ if (n < 1) ++ break; ++ if (cp[n - 1] == '\n') ++ cp[n - 1] = '\0'; ++ ++ tmp = strchr(cp, '#'); /* remove comments */ ++ if (tmp) ++ *tmp = '\0'; ++ while (isspace((int)*cp)) /* remove spaces and tabs */ ++ ++cp; ++ if (*cp == '\0') /* ignore empty lines */ ++ continue; ++ ++ tmp = strsep (&cp, " \t="); ++ if (cp != NULL) ++ while (isspace((int)*cp) || *cp == '=') ++ ++cp; ++ else ++ cp = buf + n; /* empty string */ ++ ++ if (strcasecmp(tmp, key) == 0) { ++ retval = strdup(cp); ++ break; ++ } ++ } ++ fclose(fp); ++ ++ free(buf); ++ ++ return retval; ++} ++ ++void ++parse_config_file(pam_handle_t *pamh, int argc, const char **argv, ++ struct options_t *options) ++{ ++ const char *fname = NULL; ++ int i; ++ char *val; ++ ++ for (i = 0; i < argc; ++i) { ++ const char *str = pam_str_skip_prefix(argv[i], "conf="); ++ ++ if (str != NULL) { ++ fname = str; ++ } ++ } ++ ++ if (fname == NULL) { ++ fname = PWHISTORY_DEFAULT_CONF; ++ } ++ ++ val = pwhistory_search_key (pamh, fname, "debug"); ++ if (val != NULL) { ++ options->debug = 1; ++ free(val); ++ } ++ ++ val = pwhistory_search_key (pamh, fname, "enforce_for_root"); ++ if (val != NULL) { ++ options->enforce_for_root = 1; ++ free(val); ++ } ++ ++ val = pwhistory_search_key (pamh, fname, "remember"); ++ if (val != NULL) { ++ unsigned int temp; ++ if (sscanf(val, "%u", &temp) != 1) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for remember argument"); ++ } else { ++ options->remember = temp; ++ } ++ free(val); ++ } ++ ++ val = pwhistory_search_key (pamh, fname, "retry"); ++ if (val != NULL) { ++ unsigned int temp; ++ if (sscanf(val, "%u", &temp) != 1) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for retry argument"); ++ } else { ++ options->tries = temp; ++ } ++ free(val); ++ } ++ ++ val = pwhistory_search_key (pamh, fname, "file"); ++ if (val != NULL) { ++ if (*val != '/') { ++ pam_syslog (pamh, LOG_ERR, ++ "File path should be absolute: %s", val); ++ } else { ++ options->filename = val; ++ } ++ } ++} +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h +--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.781355775 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h 2022-09-29 10:13:35.781355775 +0200 +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (c) 2022 Iker Pedrosa ++ * ++ * 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. ++ */ ++ ++#ifndef _PWHISTORY_CONFIG_H ++#define _PWHISTORY_CONFIG_H ++ ++#include ++ ++struct options_t { ++ int debug; ++ int enforce_for_root; ++ int remember; ++ int tries; ++ const char *filename; ++}; ++typedef struct options_t options_t; ++ ++void ++parse_config_file(pam_handle_t *pamh, int argc, const char **argv, ++ struct options_t *options); ++ ++#endif /* _PWHISTORY_CONFIG_H */ +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf +--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.781355775 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf 2022-09-29 10:13:35.781355775 +0200 +@@ -0,0 +1,21 @@ ++# Configuration for remembering the last passwords used by a user. ++# ++# Enable the debugging logs. ++# Enabled if option is present. ++# debug ++# ++# root account's passwords are also remembered. ++# Enabled if option is present. ++# enforce_for_root ++# ++# Number of passwords to remember. ++# The default is 10. ++# remember = 10 ++# ++# Number of times to prompt for the password. ++# The default is 1. ++# retry = 1 ++# ++# The directory where the last passwords are kept. ++# The default is /etc/security/opasswd. ++# file = /etc/security/opasswd diff --git a/SOURCES/pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch b/SOURCES/pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch new file mode 100644 index 0000000..37b3e72 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch @@ -0,0 +1,111 @@ +From a7453aeeb398d6cbb7a709c4e2a1d75905220fff Mon Sep 17 00:00:00 2001 +From: Stanislav Zidek +Date: Fri, 16 Apr 2021 19:14:18 +0200 +Subject: [PATCH] pam_userdb: Prevent garbage characters from db + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791965 +--- + modules/pam_userdb/pam_userdb.8.xml | 3 +- + modules/pam_userdb/pam_userdb.c | 56 +++++++++++++++++------------ + 2 files changed, 36 insertions(+), 23 deletions(-) + +diff --git a/modules/pam_userdb/pam_userdb.8.xml b/modules/pam_userdb/pam_userdb.8.xml +index fa628ada..bce92850 100644 +--- a/modules/pam_userdb/pam_userdb.8.xml ++++ b/modules/pam_userdb/pam_userdb.8.xml +@@ -100,7 +100,8 @@ + + + +- Print debug information. ++ Print debug information. Note that password hashes, both from db ++ and computed, will be printed to syslog. + + + +diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c +index dc2ca232..d59801bf 100644 +--- a/modules/pam_userdb/pam_userdb.c ++++ b/modules/pam_userdb/pam_userdb.c +@@ -194,7 +194,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + } + + if (data.dptr != NULL) { +- int compare = 0; ++ int compare = -2; + + if (ctrl & PAM_KEY_ONLY_ARG) + { +@@ -209,36 +209,48 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + char *cryptpw = NULL; + + if (data.dsize < 13) { +- compare = -2; ++ /* hash is too short */ ++ pam_syslog(pamh, LOG_INFO, "password hash in database is too short"); + } else if (ctrl & PAM_ICASE_ARG) { +- compare = -2; ++ pam_syslog(pamh, LOG_INFO, ++ "case-insensitive comparison only works with plaintext passwords"); + } else { ++ /* libdb is not guaranteed to produce null terminated strings */ ++ char *pwhash = strndup(data.dptr, data.dsize); ++ ++ if (pwhash == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "strndup failed: data.dptr"); ++ } else { + #ifdef HAVE_CRYPT_R +- struct crypt_data *cdata = NULL; +- cdata = malloc(sizeof(*cdata)); +- if (cdata != NULL) { +- cdata->initialized = 0; +- cryptpw = crypt_r(pass, data.dptr, cdata); +- } ++ struct crypt_data *cdata = NULL; ++ cdata = malloc(sizeof(*cdata)); ++ if (cdata == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "malloc failed: struct crypt_data"); ++ } else { ++ cdata->initialized = 0; ++ cryptpw = crypt_r(pass, pwhash, cdata); ++ } + #else +- cryptpw = crypt (pass, data.dptr); ++ cryptpw = crypt (pass, pwhash); + #endif +- if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) { +- compare = memcmp(data.dptr, cryptpw, data.dsize); +- } else { +- compare = -2; +- if (ctrl & PAM_DEBUG_ARG) { +- if (cryptpw) +- pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ"); +- else +- pam_syslog(pamh, LOG_INFO, "crypt() returned NULL"); ++ if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) { ++ compare = memcmp(data.dptr, cryptpw, data.dsize); ++ } else { ++ if (ctrl & PAM_DEBUG_ARG) { ++ if (cryptpw) { ++ pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ"); ++ pam_syslog(pamh, LOG_INFO, "computed hash: %s", cryptpw); ++ } else { ++ pam_syslog(pamh, LOG_ERR, "crypt() returned NULL"); ++ } ++ } + } +- } + #ifdef HAVE_CRYPT_R +- free(cdata); ++ free(cdata); + #endif ++ } ++ free(pwhash); + } +- + } else { + + /* Unknown password encryption method - +-- +2.30.2 + diff --git a/SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch b/SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch new file mode 100644 index 0000000..4881a5e --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch @@ -0,0 +1,75 @@ +diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/configure.ac +--- Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.169146826 +0200 ++++ Linux-PAM-1.3.1/configure.ac 2022-06-22 16:43:54.343373619 +0200 +@@ -615,12 +615,6 @@ if test x"$opt_uidmin" == x; then + fi + AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.]) + +-AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=],[default value for system user min uid (101)]), opt_sysuidmin=$withval) +-if test x"$opt_sysuidmin" == x; then +- opt_sysuidmin=101 +-fi +-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.]) +- + AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval) + if test x"$opt_kerneloverflowuid" == x; then + opt_kerneloverflowuid=65534 +diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml +--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.155146722 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml 2022-06-22 16:41:09.169146826 +0200 +@@ -31,7 +31,7 @@ + pam_usertype.so is designed to succeed or fail authentication + based on type of the account of the authenticated user. + The type of the account is decided with help of +- SYS_UID_MIN and SYS_UID_MAX ++ SYS_UID_MAX + settings in /etc/login.defs. One use is to select + whether to load other modules based on this test. + +diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c +--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.155146722 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2022-06-22 16:41:09.169146826 +0200 +@@ -277,7 +277,6 @@ static int + pam_usertype_is_system(pam_handle_t *pamh, uid_t uid) + { + uid_t uid_min; +- uid_t sys_min; + uid_t sys_max; + + if (uid == (uid_t)-1) { +@@ -285,21 +284,19 @@ pam_usertype_is_system(pam_handle_t *pam + return PAM_USER_UNKNOWN; + } + +- if (uid <= 99) { +- /* Reserved. */ +- return PAM_SUCCESS; +- } +- + if (uid == PAM_USERTYPE_OVERFLOW_UID) { + /* nobody */ + return PAM_SUCCESS; + } + + uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN); +- sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN); + sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1); + +- return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR; ++ if (uid <= sys_max && uid < uid_min) { ++ return PAM_SUCCESS; ++ } ++ ++ return PAM_AUTH_ERR; + } + + static int +@@ -336,7 +333,7 @@ pam_usertype_evaluate(struct pam_usertyp + + /** + * Arguments: +- * - issystem: uid in ++ * - issystem: uid less than SYS_UID_MAX + * - isregular: not issystem + * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if) + * - audit: log unknown users to syslog diff --git a/SOURCES/pam-1.3.1-pam-usertype.patch b/SOURCES/pam-1.3.1-pam-usertype.patch new file mode 100644 index 0000000..bada491 --- /dev/null +++ b/SOURCES/pam-1.3.1-pam-usertype.patch @@ -0,0 +1,712 @@ +diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype Linux-PAM-1.3.1/configure.ac +--- Linux-PAM-1.3.1/configure.ac.pam-usertype 2020-05-15 10:03:27.247468160 +0200 ++++ Linux-PAM-1.3.1/configure.ac 2020-05-15 10:03:27.270468089 +0200 +@@ -606,6 +606,27 @@ AC_SUBST([HAVE_KEY_MANAGEMENT], $HAVE_KE + + AM_CONDITIONAL([HAVE_KEY_MANAGEMENT], [test "$have_key_syscalls" = 1]) + ++dnl ++dnl Get values for default uid ranges in login.defs used in pam_usertype ++dnl ++AC_ARG_WITH([uidmin], AS_HELP_STRING([--with-uidmin=],[default value for regular user min uid (1000)]), opt_uidmin=$withval) ++if test x"$opt_uidmin" == x; then ++ opt_uidmin=1000 ++fi ++AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.]) ++ ++AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=],[default value for system user min uid (101)]), opt_sysuidmin=$withval) ++if test x"$opt_sysuidmin" == x; then ++ opt_sysuidmin=101 ++fi ++AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.]) ++ ++AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval) ++if test x"$opt_kerneloverflowuid" == x; then ++ opt_kerneloverflowuid=65534 ++fi ++AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.]) ++ + dnl Files to be created from when we run configure + AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \ + libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \ +@@ -636,6 +657,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefil + modules/pam_timestamp/Makefile modules/pam_tty_audit/Makefile \ + modules/pam_umask/Makefile \ + modules/pam_unix/Makefile modules/pam_userdb/Makefile \ ++ modules/pam_usertype/Makefile \ + modules/pam_warn/Makefile modules/pam_wheel/Makefile \ + modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \ + doc/man/Makefile doc/sag/Makefile doc/adg/Makefile \ +diff -up Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/Makefile.am +--- Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype 2020-05-15 10:03:27.247468160 +0200 ++++ Linux-PAM-1.3.1/modules/Makefile.am 2020-05-15 10:03:27.270468089 +0200 +@@ -12,7 +12,7 @@ SUBDIRS = pam_access pam_cracklib pam_de + pam_selinux pam_sepermit pam_shells pam_stress \ + pam_succeed_if pam_time pam_timestamp \ + pam_tty_audit pam_umask \ +- pam_unix pam_userdb pam_warn pam_wheel pam_xauth ++ pam_unix pam_userdb pam_usertype pam_warn pam_wheel pam_xauth + + CLEANFILES = *~ + +diff -up Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am +--- Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype 2020-05-15 10:03:27.270468089 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am 2020-05-15 10:03:27.270468089 +0200 +@@ -0,0 +1,34 @@ ++# ++# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk ++# Copyright (c) 2020 Red Hat, Inc. ++# ++ ++CLEANFILES = *~ ++MAINTAINERCLEANFILES = $(MANS) README ++ ++EXTRA_DIST = README ${MANS} ${XMLS} tst-pam_usertype ++ ++TESTS = tst-pam_usertype ++ ++man_MANS = pam_usertype.8 ++ ++XMLS = README.xml pam_usertype.8.xml ++ ++securelibdir = $(SECUREDIR) ++secureconfdir = $(SCONFIGDIR) ++ ++AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ ++ $(WARN_CFLAGS) ++AM_LDFLAGS = -no-undefined -avoid-version -module ++if HAVE_VERSIONING ++ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map ++endif ++ ++securelib_LTLIBRARIES = pam_usertype.la ++pam_usertype_la_LIBADD = $(top_builddir)/libpam/libpam.la ++ ++if ENABLE_REGENERATE_MAN ++noinst_DATA = README ++README: pam_usertype.8.xml ++-include $(top_srcdir)/Make.xml.rules ++endif +diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml +--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype 2020-05-15 10:03:27.270468089 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml 2020-05-15 10:03:27.270468089 +0200 +@@ -0,0 +1,170 @@ ++ ++ ++ ++ ++ ++ ++ pam_usertype ++ 8 ++ Linux-PAM ++ ++ ++ ++ pam_usertype ++ check if the authenticated user is a system or regular account ++ ++ ++ ++ ++ ++ pam_usertype.so ++ flag ++ condition ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ pam_usertype.so is designed to succeed or fail authentication ++ based on type of the account of the authenticated user. ++ The type of the account is decided with help of ++ SYS_UID_MIN and SYS_UID_MAX ++ settings in /etc/login.defs. One use is to select ++ whether to load other modules based on this test. ++ ++ ++ ++ The module should be given only one condition as module argument. ++ Authentication will succeed only if the condition is met. ++ ++ ++ ++ ++ OPTIONS ++ ++ The following flags are supported: ++ ++ ++ ++ ++ ++ ++ ++ Evaluate conditions using the account of the user whose UID ++ the application is running under instead of the user being ++ authenticated. ++ ++ ++ ++ ++ ++ ++ ++ Log unknown users to the system log. ++ ++ ++ ++ ++ ++ ++ Available conditions are: ++ ++ ++ ++ ++ ++ ++ Succeed if the user is a system user. ++ ++ ++ ++ ++ ++ Succeed if the user is a regular user. ++ ++ ++ ++ ++ ++ ++ MODULE TYPES PROVIDED ++ ++ All module types (, , ++ and ) are provided. ++ ++ ++ ++ ++ RETURN VALUES ++ ++ ++ ++ PAM_SUCCESS ++ ++ ++ The condition was true. ++ ++ ++ ++ ++ ++ PAM_AUTH_ERR ++ ++ ++ The condition was false. ++ ++ ++ ++ ++ ++ PAM_SERVICE_ERR ++ ++ ++ A service error occurred or the arguments can't be ++ parsed correctly. ++ ++ ++ ++ ++ ++ PAM_USER_UNKNOWN ++ ++ ++ User was not found. ++ ++ ++ ++ ++ ++ ++ ++ ++ EXAMPLES ++ ++ Skip remaining modules if the user is a system user: ++ ++ ++account sufficient pam_usertype.so issystem ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ login.defs5 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ Pavel Březina <pbrezina@redhat.com> ++ ++ +diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c +--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype 2020-05-15 10:03:27.270468089 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2020-05-15 10:16:08.053198025 +0200 +@@ -0,0 +1,394 @@ ++/****************************************************************************** ++ * Check user type based on login.defs. ++ * ++ * Copyright (c) 2020 Red Hat, Inc. ++ * Written by Pavel Březina ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PAM_SM_AUTH ++#define PAM_SM_ACCOUNT ++#define PAM_SM_SESSION ++#define PAM_SM_PASSWORD ++ ++#include ++#include ++#include ++ ++#define LOGIN_DEFS "/etc/login.defs" ++ ++enum pam_usertype_op { ++ OP_IS_SYSTEM, ++ OP_IS_REGULAR, ++ ++ OP_SENTINEL ++}; ++ ++struct pam_usertype_opts { ++ enum pam_usertype_op op; ++ int use_uid; ++ int audit; ++}; ++ ++static int ++pam_usertype_parse_args(struct pam_usertype_opts *opts, ++ pam_handle_t *pamh, ++ int argc, ++ const char **argv) ++{ ++ int i; ++ ++ memset(opts, 0, sizeof(struct pam_usertype_opts)); ++ opts->op = OP_SENTINEL; ++ ++ for (i = 0; i < argc; i++) { ++ if (strcmp(argv[i], "use_uid") == 0) { ++ opts->use_uid = 1; ++ } else if (strcmp(argv[i], "audit") == 0) { ++ opts->audit = 1; ++ } else if (strcmp(argv[i], "issystem") == 0) { ++ opts->op = OP_IS_SYSTEM; ++ } else if (strcmp(argv[i], "isregular") == 0) { ++ opts->op = OP_IS_REGULAR; ++ } else { ++ pam_syslog(pamh, LOG_WARNING, "Unknown argument: %s", argv[i]); ++ /* Just continue. */ ++ } ++ } ++ ++ if (opts->op == OP_SENTINEL) { ++ pam_syslog(pamh, LOG_ERR, "Operation not specified"); ++ return PAM_SERVICE_ERR; ++ } ++ ++ return PAM_SUCCESS; ++} ++ ++static int ++pam_usertype_get_uid(struct pam_usertype_opts *opts, ++ pam_handle_t *pamh, ++ uid_t *_uid) ++{ ++ struct passwd *pwd; ++ const void *prompt; ++ const char *username; ++ int ret; ++ ++ /* Get uid of user that runs the application. */ ++ if (opts->use_uid) { ++ pwd = pam_modutil_getpwuid(pamh, getuid()); ++ if (pwd == NULL) { ++ pam_syslog(pamh, LOG_ERR, ++ "error retrieving information about user %lu", ++ (unsigned long)getuid()); ++ return PAM_USER_UNKNOWN; ++ } ++ ++ *_uid = pwd->pw_uid; ++ return PAM_SUCCESS; ++ } ++ ++ /* Get uid of user that is being authenticated. */ ++ ret = pam_get_item(pamh, PAM_USER_PROMPT, &prompt); ++ if (ret != PAM_SUCCESS || prompt == NULL || strlen(prompt) == 0) { ++ prompt = "login: "; ++ } ++ ++ ret = pam_get_user(pamh, &username, prompt); ++ if (ret != PAM_SUCCESS || username == NULL) { ++ pam_syslog(pamh, LOG_ERR, "error retrieving user name: %s", ++ pam_strerror(pamh, ret)); ++ return ret; ++ } ++ ++ pwd = pam_modutil_getpwnam(pamh, username); ++ if (pwd == NULL) { ++ if (opts->audit) { ++ pam_syslog(pamh, LOG_NOTICE, ++ "error retrieving information about user %s", username); ++ } ++ ++ return PAM_USER_UNKNOWN; ++ } ++ ++ *_uid = pwd->pw_uid; ++ ++ return PAM_SUCCESS; ++} ++ ++#define MAX_UID_VALUE 0xFFFFFFFFUL ++ ++/* lookup a value for key in login.defs file or similar key value format */ ++char * ++pam_usertype_search_key(pam_handle_t *pamh UNUSED, ++ const char *file_name, ++ const char *key) ++{ ++ FILE *fp; ++ char *buf = NULL; ++ size_t buflen = 0; ++ char *retval = NULL; ++ ++ fp = fopen(file_name, "r"); ++ if (NULL == fp) ++ return NULL; ++ ++ while (!feof(fp)) { ++ char *tmp, *cp; ++#if defined(HAVE_GETLINE) ++ ssize_t n = getline(&buf, &buflen, fp); ++#elif defined (HAVE_GETDELIM) ++ ssize_t n = getdelim(&buf, &buflen, '\n', fp); ++#else ++ ssize_t n; ++ ++ if (buf == NULL) { ++ buflen = BUF_SIZE; ++ buf = malloc(buflen); ++ if (buf == NULL) { ++ fclose(fp); ++ return NULL; ++ } ++ } ++ buf[0] = '\0'; ++ if (fgets(buf, buflen - 1, fp) == NULL) ++ break; ++ else if (buf != NULL) ++ n = strlen(buf); ++ else ++ n = 0; ++#endif /* HAVE_GETLINE / HAVE_GETDELIM */ ++ cp = buf; ++ ++ if (n < 1) ++ break; ++ if (cp[n - 1] == '\n') ++ cp[n - 1] = '\0'; ++ ++ tmp = strchr(cp, '#'); /* remove comments */ ++ if (tmp) ++ *tmp = '\0'; ++ while (isspace((int)*cp)) /* remove spaces and tabs */ ++ ++cp; ++ if (*cp == '\0') /* ignore empty lines */ ++ continue; ++ ++ tmp = strsep (&cp, " \t="); ++ if (cp != NULL) ++ while (isspace((int)*cp) || *cp == '=') ++ ++cp; ++ else ++ cp = ""; ++ ++ if (strcasecmp(tmp, key) == 0) { ++ retval = strdup(cp); ++ break; ++ } ++ } ++ fclose(fp); ++ ++ free(buf); ++ ++ return retval; ++} ++ ++static uid_t ++pam_usertype_get_id(pam_handle_t *pamh, ++ const char *key, ++ uid_t default_value) ++{ ++ unsigned long ul; ++ char *value; ++ char *ep; ++ uid_t uid; ++ ++ value = pam_usertype_search_key(pamh, LOGIN_DEFS, key); ++ if (value == NULL) { ++ return default_value; ++ } ++ ++ /* taken from get_lastlog_uid_max() */ ++ ep = value + strlen(value); ++ while (ep > value && isspace(*(--ep))) { ++ *ep = '\0'; ++ } ++ ++ errno = 0; ++ ul = strtoul(value, &ep, 10); ++ if (!(ul >= MAX_UID_VALUE ++ || (uid_t)ul >= MAX_UID_VALUE ++ || (errno != 0 && ul == 0) ++ || value == ep ++ || *ep != '\0')) { ++ uid = (uid_t)ul; ++ } else { ++ uid = default_value; ++ } ++ ++ free(value); ++ ++ return uid; ++} ++ ++static int ++pam_usertype_is_system(pam_handle_t *pamh, uid_t uid) ++{ ++ uid_t uid_min; ++ uid_t sys_min; ++ uid_t sys_max; ++ ++ if (uid == (uid_t)-1) { ++ pam_syslog(pamh, LOG_WARNING, "invalid uid"); ++ return PAM_USER_UNKNOWN; ++ } ++ ++ if (uid <= 99) { ++ /* Reserved. */ ++ return PAM_SUCCESS; ++ } ++ ++ if (uid == PAM_USERTYPE_OVERFLOW_UID) { ++ /* nobody */ ++ return PAM_SUCCESS; ++ } ++ ++ uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN); ++ sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN); ++ sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1); ++ ++ return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR; ++} ++ ++static int ++pam_usertype_is_regular(pam_handle_t *pamh, uid_t uid) ++{ ++ int ret; ++ ++ ret = pam_usertype_is_system(pamh, uid); ++ switch (ret) { ++ case PAM_SUCCESS: ++ return PAM_AUTH_ERR; ++ case PAM_USER_UNKNOWN: ++ return PAM_USER_UNKNOWN; ++ default: ++ return PAM_SUCCESS; ++ } ++} ++ ++static int ++pam_usertype_evaluate(struct pam_usertype_opts *opts, ++ pam_handle_t *pamh, ++ uid_t uid) ++{ ++ switch (opts->op) { ++ case OP_IS_SYSTEM: ++ return pam_usertype_is_system(pamh, uid); ++ case OP_IS_REGULAR: ++ return pam_usertype_is_regular(pamh, uid); ++ default: ++ pam_syslog(pamh, LOG_ERR, "Unknown operation: %d", opts->op); ++ return PAM_SERVICE_ERR; ++ } ++} ++ ++/** ++ * Arguments: ++ * - issystem: uid in ++ * - isregular: not issystem ++ * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if) ++ * - audit: log unknown users to syslog ++ */ ++int ++pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, ++ int argc, const char **argv) ++{ ++ struct pam_usertype_opts opts; ++ uid_t uid; ++ int ret; ++ ++ ret = pam_usertype_parse_args(&opts, pamh, argc, argv); ++ if (ret != PAM_SUCCESS) { ++ return ret; ++ } ++ ++ ret = pam_usertype_get_uid(&opts, pamh, &uid); ++ if (ret != PAM_SUCCESS) { ++ return ret; ++ } ++ ++ return pam_usertype_evaluate(&opts, pamh, uid); ++} ++ ++int ++pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED, ++ int argc UNUSED, const char **argv UNUSED) ++{ ++ return PAM_IGNORE; ++} ++ ++int ++pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return pam_sm_authenticate(pamh, flags, argc, argv); ++} ++ ++int ++pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return pam_sm_authenticate(pamh, flags, argc, argv); ++} ++ ++int ++pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return pam_sm_authenticate(pamh, flags, argc, argv); ++} ++ ++int ++pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return pam_sm_authenticate(pamh, flags, argc, argv); ++} +diff -up Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/README.xml +--- Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype 2020-05-15 10:03:27.270468089 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/README.xml 2020-05-15 10:03:27.270468089 +0200 +@@ -0,0 +1,41 @@ ++ ++ ++--> ++]> ++ ++
++ ++ ++ ++ ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="pam_usertype.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_usertype-name"]/*)'/> ++ ++ ++ ++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
+diff -up Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype +--- Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype 2020-05-15 10:03:27.270468089 +0200 ++++ Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype 2020-05-15 10:03:27.270468089 +0200 +@@ -0,0 +1,2 @@ ++#!/bin/sh ++../../tests/tst-dlopen .libs/pam_usertype.so diff --git a/SOURCES/pam-1.3.1-tty-audit-manfix.patch b/SOURCES/pam-1.3.1-tty-audit-manfix.patch new file mode 100644 index 0000000..3d17963 --- /dev/null +++ b/SOURCES/pam-1.3.1-tty-audit-manfix.patch @@ -0,0 +1,33 @@ +From e31dd6c7d0faa7a06d3ebd50a0b6957b9f822d15 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Wed, 7 Aug 2019 18:13:57 +0200 +Subject: [PATCH] pam_tty_audit: Manual page clarification about password + logging + +* modules/pam_tty_audit/pam_tty_audit.8.xml: Explanation why passwords +can be sometimes logged even when the option is not set. +--- + modules/pam_tty_audit/pam_tty_audit.8.xml | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/modules/pam_tty_audit/pam_tty_audit.8.xml b/modules/pam_tty_audit/pam_tty_audit.8.xml +index 59a3406..e346c68 100644 +--- a/modules/pam_tty_audit/pam_tty_audit.8.xml ++++ b/modules/pam_tty_audit/pam_tty_audit.8.xml +@@ -149,6 +149,13 @@ + greater than or equal to min_uid will be + matched. +
++ ++ Please note that passwords in some circumstances may be logged by TTY auditing ++ even if the is not used. For example, all input to ++ an ssh session will be logged - even if there is a password being typed into ++ some software running at the remote host because only the local TTY state ++ affects the local TTY auditing. ++ + + + +-- +2.20.1 + diff --git a/SOURCES/pam-1.3.1-unix-default-rounds.patch b/SOURCES/pam-1.3.1-unix-default-rounds.patch new file mode 100644 index 0000000..bb4a156 --- /dev/null +++ b/SOURCES/pam-1.3.1-unix-default-rounds.patch @@ -0,0 +1,12 @@ +diff -up Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c.unix-default-rounds Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c +--- Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c.unix-default-rounds 2023-11-02 09:59:54.533238124 +0100 ++++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c 2023-11-02 10:40:58.017404936 +0100 +@@ -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; + + /* */ diff --git a/SOURCES/pam-1.3.1-unix-enable-bcrypt.patch b/SOURCES/pam-1.3.1-unix-enable-bcrypt.patch new file mode 100644 index 0000000..9264765 --- /dev/null +++ b/SOURCES/pam-1.3.1-unix-enable-bcrypt.patch @@ -0,0 +1,174 @@ +From f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +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)) { +-- +2.41.0 + +diff -up Linux-PAM-1.3.1/configure.ac.legacy-xcrypt Linux-PAM-1.3.1/configure.ac +--- Linux-PAM-1.3.1/configure.ac.legacy-xcrypt 2023-10-26 12:08:46.896437225 +0200 ++++ Linux-PAM-1.3.1/configure.ac 2023-10-26 12:10:38.289654696 +0200 +@@ -395,19 +395,32 @@ AC_SUBST(LIBAUDIT) + AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS], + [test "x$HAVE_AUDIT_TTY_STATUS" = xyes]) + +-AC_CHECK_HEADERS(xcrypt.h crypt.h) +-AS_IF([test "x$ac_cv_header_xcrypt_h" = "xyes"], +- [crypt_libs="xcrypt crypt"], +- [crypt_libs="crypt"]) ++AC_CHECK_HEADERS(crypt.h) + + BACKUP_LIBS=$LIBS +-AC_SEARCH_LIBS([crypt],[$crypt_libs], LIBCRYPT="${ac_lib:+-l$ac_lib}", LIBCRYPT="") +-AC_CHECK_FUNCS(crypt_r crypt_gensalt_r) ++LIBCRYPT="" ++PKG_CHECK_MODULES([CRYPT], [libcrypt], [ ++ CFLAGS="$CFLAGS $CRYPT_CFLAGS" ++ CPPFLAGS="$CPPFLAGS $CRYPT_CFLAGS" ++ LIBS="$LIBS $CRYPT_LIBS" ++ LIBCRYPT="$CRYPT_LIBS" ++], [ ++ AC_SEARCH_LIBS([crypt_gensalt_rn],[crypt]) ++ case "$ac_cv_search_crypt_gensalt_rn" in ++ -l*) LIBCRYPT="$ac_cv_search_crypt_gensalt_rn" ;; ++ no) AC_SEARCH_LIBS([crypt_r],[crypt]) ++ case "$ac_cv_search_crypt_r" in ++ -l*) LIBCRYPT="$ac_cv_search_crypt_r" ;; ++ no ) AC_SEARCH_LIBS([crypt],[crypt]) ++ case "$ac_cv_search_crypt" in ++ -l*) LIBCRYPT="$ac_cv_search_crypt" ;; ++ esac ;; ++ esac ;; ++ esac ++]) ++AC_CHECK_FUNCS([crypt_r]) + LIBS=$BACKUP_LIBS + AC_SUBST(LIBCRYPT) +-if test "$LIBCRYPT" = "-lxcrypt" -a "$ac_cv_header_xcrypt_h" = "yes" ; then +- AC_DEFINE([HAVE_LIBXCRYPT], 1, [Define to 1 if xcrypt support should be compiled in.]) +-fi + + AC_ARG_WITH([randomdev], AS_HELP_STRING([--with-randomdev=(|yes|no)],[use specified random device instead of /dev/urandom or 'no' to disable]), opt_randomdev=$withval) + if test "$opt_randomdev" = yes -o -z "$opt_randomdev"; then +diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c +--- Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c.legacy-xcrypt 2023-10-26 12:08:46.896437225 +0200 ++++ Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c 2023-10-26 12:11:14.437725259 +0200 +@@ -52,9 +52,7 @@ + #include + #include + +-#if defined (HAVE_XCRYPT_H) +-#include +-#elif defined (HAVE_CRYPT_H) ++#ifdef HAVE_CRYPT_H + #include + #endif + +diff -up Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c +--- Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c.legacy-xcrypt 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c 2023-10-26 12:08:46.896437225 +0200 +@@ -29,9 +29,7 @@ + #include + #include + #include +-#ifdef HAVE_LIBXCRYPT +-#include +-#elif defined(HAVE_CRYPT_H) ++#ifdef HAVE_CRYPT_H + #include + #endif + +diff -up Linux-PAM-1.3.1/modules/pam_unix/passverify.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_unix/passverify.c +--- Linux-PAM-1.3.1/modules/pam_unix/passverify.c.legacy-xcrypt 2023-10-26 12:08:46.895437223 +0200 ++++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c 2023-10-26 12:16:25.470320408 +0200 +@@ -19,9 +19,7 @@ + #include + #include + #include +-#ifdef HAVE_LIBXCRYPT +-#include +-#elif defined(HAVE_CRYPT_H) ++#ifdef HAVE_CRYPT_H + #include + #endif + +@@ -406,23 +404,19 @@ PAMH_ARG_DECL(char * create_password_has + return crypted; + } + +-#ifdef HAVE_CRYPT_GENSALT_R +- if (on(UNIX_BLOWFISH_PASS, ctrl)) { +- char entropy[17]; +- crypt_make_salt(entropy, sizeof(entropy) - 1); +- sp = crypt_gensalt_r (algoid, rounds, +- entropy, sizeof(entropy), +- salt, sizeof(salt)); +- } else { +-#endif +- sp = stpcpy(salt, algoid); +- if (on(UNIX_ALGO_ROUNDS, ctrl)) { +- sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds); +- } +- crypt_make_salt(sp, 16); +-#ifdef HAVE_CRYPT_GENSALT_R ++#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 ++ sp = stpcpy(salt, algoid); ++ if (on(UNIX_ALGO_ROUNDS, ctrl)) { ++ sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds); + } +-#endif ++ crypt_make_salt(sp, 16); ++#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */ + #ifdef HAVE_CRYPT_R + sp = NULL; + cdata = malloc(sizeof(*cdata)); +diff -up Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c +--- Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c.legacy-xcrypt 2023-10-26 12:08:46.880437194 +0200 ++++ Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c 2023-10-26 12:08:46.896437225 +0200 +@@ -17,9 +17,7 @@ + #include + #include + #include +-#ifdef HAVE_LIBXCRYPT +-#include +-#elif defined(HAVE_CRYPT_H) ++#ifdef HAVE_CRYPT_H + #include + #endif + diff --git a/SOURCES/pam-1.3.1-unix-improve-logging.patch b/SOURCES/pam-1.3.1-unix-improve-logging.patch new file mode 100644 index 0000000..682b4d5 --- /dev/null +++ b/SOURCES/pam-1.3.1-unix-improve-logging.patch @@ -0,0 +1,57 @@ +From a6845905869ccabb5eb802be37241eabec085dc7 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Mon, 14 Oct 2019 16:52:46 +0200 +Subject: [PATCH] pam_unix: Add logging useful for debugging problems + +Two messages added about obtaining the username are guarded +by the debug option as these should not be normally +logged - they can be useful for debugging but they do not +indicate any special condition. + +The message about authenticating user with blank password is +still just LOG_DEBUG priority but it is logged unconditionally +because it is somewhat extraordinary condition to have an user +with blank password. + +* modules/pam_unix/pam_unix_auth.c (pam_sm_authenticate): Replace + D() macro calls which are not enabled on production builds with + regular pam_syslog() calls. +--- + modules/pam_unix/pam_unix_auth.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c +index 681e49d..3fca945 100644 +--- a/modules/pam_unix/pam_unix_auth.c ++++ b/modules/pam_unix/pam_unix_auth.c +@@ -130,15 +130,16 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) + AUTH_RETURN; + } + if (on(UNIX_DEBUG, ctrl)) +- D(("username [%s] obtained", name)); ++ pam_syslog(pamh, LOG_DEBUG, "username [%s] obtained", name); + } else { +- D(("trouble reading username")); + if (retval == PAM_CONV_AGAIN) { + D(("pam_get_user/conv() function is not ready yet")); + /* it is safe to resume this function so we translate this + * retval to the value that indicates we're happy to resume. + */ + retval = PAM_INCOMPLETE; ++ } else if (on(UNIX_DEBUG, ctrl)) { ++ pam_syslog(pamh, LOG_DEBUG, "could not obtain username"); + } + AUTH_RETURN; + } +@@ -146,7 +147,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) + /* if this user does not have a password... */ + + if (_unix_blankpasswd(pamh, ctrl, name)) { +- D(("user '%s' has blank passwd", name)); ++ pam_syslog(pamh, LOG_DEBUG, "user [%s] has blank password; authenticated without it", name); + name = NULL; + retval = PAM_SUCCESS; + AUTH_RETURN; +-- +2.20.1 + diff --git a/SOURCES/pam-1.3.1-wheel-pam_ruser-fallback.patch b/SOURCES/pam-1.3.1-wheel-pam_ruser-fallback.patch new file mode 100644 index 0000000..a92f884 --- /dev/null +++ b/SOURCES/pam-1.3.1-wheel-pam_ruser-fallback.patch @@ -0,0 +1,134 @@ +From 6bf9b454eb971083f0cce49faa2aa1cde329ff5d Mon Sep 17 00:00:00 2001 +From: ikerexxe +Date: Wed, 26 Aug 2020 14:44:23 +0200 +Subject: [PATCH 1/3] pam_wheel: improve coding style + +modules/pam_wheel/pam_wheel.c: improve indentation and explicitly state +condition statements +--- + modules/pam_wheel/pam_wheel.c | 36 ++++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 17 deletions(-) + +diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c +index a025ebaf..94cb7d89 100644 +--- a/modules/pam_wheel/pam_wheel.c ++++ b/modules/pam_wheel/pam_wheel.c +@@ -130,25 +130,27 @@ perform_check (pam_handle_t *pamh, int ctrl, const char *use_group) + } + + if (ctrl & PAM_USE_UID_ARG) { +- tpwd = pam_modutil_getpwuid (pamh, getuid()); +- if (!tpwd) { +- if (ctrl & PAM_DEBUG_ARG) { ++ tpwd = pam_modutil_getpwuid (pamh, getuid()); ++ if (tpwd == NULL) { ++ if (ctrl & PAM_DEBUG_ARG) { + pam_syslog(pamh, LOG_NOTICE, "who is running me ?!"); +- } +- return PAM_SERVICE_ERR; +- } +- fromsu = tpwd->pw_name; ++ } ++ return PAM_SERVICE_ERR; ++ } ++ fromsu = tpwd->pw_name; + } else { +- fromsu = pam_modutil_getlogin(pamh); +- if (fromsu) { +- tpwd = pam_modutil_getpwnam (pamh, fromsu); +- } +- if (!fromsu || !tpwd) { +- if (ctrl & PAM_DEBUG_ARG) { +- pam_syslog(pamh, LOG_NOTICE, "who is running me ?!"); +- } +- return PAM_SERVICE_ERR; +- } ++ fromsu = pam_modutil_getlogin(pamh); ++ ++ if (fromsu != NULL) { ++ tpwd = pam_modutil_getpwnam (pamh, fromsu); ++ } ++ ++ if (fromsu == NULL || tpwd == NULL) { ++ if (ctrl & PAM_DEBUG_ARG) { ++ pam_syslog(pamh, LOG_NOTICE, "who is running me ?!"); ++ } ++ return PAM_SERVICE_ERR; ++ } + } + + /* +-- +2.26.2 + + +From 9091ea1d81e85f49a221b0325d27b22ce69e444a Mon Sep 17 00:00:00 2001 +From: ikerexxe +Date: Thu, 27 Aug 2020 09:16:15 +0200 +Subject: [PATCH 2/3] pam_wheel: if getlogin fails fallback to PAM_RUSER + +modules/pam_wheel/pam_wheel.c: if getlogin fails to obtain the real user +ID, then try with PAM_RUSER. + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=1866866 +--- + modules/pam_wheel/pam_wheel.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c +index 94cb7d89..7fa3cfa9 100644 +--- a/modules/pam_wheel/pam_wheel.c ++++ b/modules/pam_wheel/pam_wheel.c +@@ -141,6 +141,16 @@ perform_check (pam_handle_t *pamh, int ctrl, const char *use_group) + } else { + fromsu = pam_modutil_getlogin(pamh); + ++ /* if getlogin fails try a fallback to PAM_RUSER */ ++ if (fromsu == NULL) { ++ const char *rhostname; ++ ++ retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhostname); ++ if (retval != PAM_SUCCESS || rhostname == NULL) { ++ retval = pam_get_item(pamh, PAM_RUSER, (const void **)&fromsu); ++ } ++ } ++ + if (fromsu != NULL) { + tpwd = pam_modutil_getpwnam (pamh, fromsu); + } +-- +2.26.2 + + +From a3a5cbf86083c43026b558e2023f597530626267 Mon Sep 17 00:00:00 2001 +From: ikerexxe +Date: Wed, 9 Sep 2020 10:32:03 +0200 +Subject: [PATCH 3/3] pam_wheel: clarify use_uid option in man page + +modules/pam_wheel/pam_wheel.8.xml: indicate that use_uid option uses the +real uid of the calling process. +--- + modules/pam_wheel/pam_wheel.8.xml | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/modules/pam_wheel/pam_wheel.8.xml b/modules/pam_wheel/pam_wheel.8.xml +index b32f5e2b..ee8c7d26 100644 +--- a/modules/pam_wheel/pam_wheel.8.xml ++++ b/modules/pam_wheel/pam_wheel.8.xml +@@ -122,9 +122,9 @@ + + + +- The check for wheel membership will be done against +- the current uid instead of the original one (useful when +- jumping with su from one account to another for example). ++ The check will be done against the real uid of the calling process, ++ instead of trying to obtain the user from the login session ++ associated with the terminal in use. + + + +-- +2.26.2 + diff --git a/SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch b/SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch new file mode 100644 index 0000000..016bb15 --- /dev/null +++ b/SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch @@ -0,0 +1,37 @@ +From 10086bc69663fa819277af244eeb5b629a2403b8 Mon Sep 17 00:00:00 2001 +From: Deepak Das +Date: Mon, 10 Oct 2022 21:21:35 +0530 +Subject: [PATCH] pam_faillock: avoid logging an erroneous consecutive login + failure message + +* modules/pam_faillock/pam_faillock.c (write_tally): Avoid logging +a consecutive login failure message for the root user in case when +even_deny_root is not set. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2082442 +--- + modules/pam_faillock/pam_faillock.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c +index ddbb90e7..ca1c7035 100644 +--- a/modules/pam_faillock/pam_faillock.c ++++ b/modules/pam_faillock/pam_faillock.c +@@ -374,9 +374,11 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies + } + close(audit_fd); + #endif +- if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO)) { +- pam_syslog(pamh, LOG_INFO, "Consecutive login failures for user %s account temporarily locked", +- opts->user); ++ if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO) && ++ ((opts->flags & FAILLOCK_FLAG_DENY_ROOT) || (opts->uid != 0))) { ++ pam_syslog(pamh, LOG_INFO, ++ "Consecutive login failures for user %s account temporarily locked", ++ opts->user); + } + } + +-- +2.38.1 + diff --git a/SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch b/SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch new file mode 100644 index 0000000..3f15eb8 --- /dev/null +++ b/SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch @@ -0,0 +1,53 @@ +From bcbf145ce925934214e48200c27c9ff736452549 Mon Sep 17 00:00:00 2001 +From: Deepak Das +Date: Mon, 10 Oct 2022 17:55:53 +0530 +Subject: [PATCH] pam_faillock: Clarify missing user faillock files after + reboot + +* modules/pam_faillock/faillock.conf.5.xml: Adding note related to missing +user specific faillock files after reboot. + +* modules/pam_faillock/pam_faillock.8.xml: Adding note related to missing +user specific faillock files after reboot. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2062512 +--- + modules/pam_faillock/faillock.conf.5.xml | 4 ++++ + modules/pam_faillock/pam_faillock.8.xml | 6 ++++++ + 2 files changed, 10 insertions(+) + +diff --git a/modules/pam_faillock/faillock.conf.5.xml b/modules/pam_faillock/faillock.conf.5.xml +index 04a84107..8faa5915 100644 +--- a/modules/pam_faillock/faillock.conf.5.xml ++++ b/modules/pam_faillock/faillock.conf.5.xml +@@ -44,6 +44,10 @@ + The directory where the user files with the failure records are kept. The + default is /var/run/faillock. + ++ ++ Note: These files will disappear after reboot on systems configured with ++ directory /var/run/faillock mounted on virtual memory. ++ + + + +diff --git a/modules/pam_faillock/pam_faillock.8.xml b/modules/pam_faillock/pam_faillock.8.xml +index 79bcbbd0..b7b7b0db 100644 +--- a/modules/pam_faillock/pam_faillock.8.xml ++++ b/modules/pam_faillock/pam_faillock.8.xml +@@ -327,6 +327,12 @@ session required pam_selinux.so open + /var/run/faillock/* + + the files logging the authentication failures for users ++ ++ Note: These files will disappear after reboot on systems configured with ++ directory /var/run/faillock mounted on virtual memory. ++ For persistent storage use the option dir= in ++ file /etc/security/faillock.conf. ++ + + + +-- +2.38.1 + diff --git a/SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch b/SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch new file mode 100644 index 0000000..80ad508 --- /dev/null +++ b/SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch @@ -0,0 +1,41 @@ +From 40c271164dbcebfc5304d0537a42fb42e6b6803c Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 26 Sep 2022 12:16:53 +0200 +Subject: [PATCH] pam_lastlog: check localtime_r() return value + +Check the return value of localtime_r() before calling strftime(). This +function crashes if the argument is NULL. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012871 + +Signed-off-by: Iker Pedrosa +--- + modules/pam_lastlog/pam_lastlog.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c +index abd048df..121e7560 100644 +--- a/modules/pam_lastlog/pam_lastlog.c ++++ b/modules/pam_lastlog/pam_lastlog.c +@@ -573,12 +573,12 @@ last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t llt + time_t lf_time; + + lf_time = utuser.ut_tv.tv_sec; +- tm = localtime_r (&lf_time, &tm_buf); +- strftime (the_time, sizeof (the_time), +- /* TRANSLATORS: "strftime options for date of last login" */ +- _(" %a %b %e %H:%M:%S %Z %Y"), tm); +- +- date = the_time; ++ if ((tm = localtime_r (&lf_time, &tm_buf)) != NULL) { ++ strftime (the_time, sizeof (the_time), ++ /* TRANSLATORS: "strftime options for date of last login" */ ++ _(" %a %b %e %H:%M:%S %Z %Y"), tm); ++ date = the_time; ++ } + } + + /* we want & have the host? */ +-- +2.38.1 + diff --git a/SOURCES/pamtmp.conf b/SOURCES/pamtmp.conf new file mode 100644 index 0000000..e4cfe2a --- /dev/null +++ b/SOURCES/pamtmp.conf @@ -0,0 +1,4 @@ +d /run/console 0755 root root - +d /run/faillock 0755 root root - +d /run/sepermit 0755 root root - +d /run/motd.d 0755 root root - diff --git a/SOURCES/password-auth.pamd b/SOURCES/password-auth.pamd new file mode 100644 index 0000000..5de6f4d --- /dev/null +++ b/SOURCES/password-auth.pamd @@ -0,0 +1,18 @@ +#%PAM-1.0 +# This file is auto-generated. +# User changes will be destroyed the next time authselect is run. +auth required pam_env.so +auth sufficient pam_unix.so try_first_pass nullok +auth required pam_deny.so + +account required pam_unix.so + +password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= +password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow +password required pam_deny.so + +session optional pam_keyinit.so revoke +session required pam_limits.so +-session optional pam_systemd.so +session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid +session required pam_unix.so diff --git a/SOURCES/postlogin.5 b/SOURCES/postlogin.5 new file mode 100644 index 0000000..3a8abcf --- /dev/null +++ b/SOURCES/postlogin.5 @@ -0,0 +1,46 @@ +.TH POSTLOGIN 5 "2010 Dec 22" "Red Hat" "Linux-PAM Manual" +.SH NAME + +postlogin \- Common configuration file for PAMified services + +.SH SYNOPSIS +.B /etc/pam.d/postlogin +.sp 2 +.SH DESCRIPTION + +The purpose of this PAM configuration file is to provide a common +place for all PAM modules which should be called after the stack +configured in +.BR system-auth +or the other common PAM configuration files. + +.sp +The +.BR postlogin +configuration file is included from all individual service configuration +files that provide login service with shell or file access. + +.SH NOTES +The modules in the postlogin configuration file are executed regardless +of the success or failure of the modules in the +.BR system-auth +configuration file. + +.SH BUGS +.sp 2 +Sometimes it would be useful to be able to skip the postlogin modules in +case the substack of the +.BR system-auth +modules failed. Unfortunately the current Linux-PAM library does not +provide any way how to achieve this. + +.SH "SEE ALSO" +pam(8), config-util(5), system-auth(5) + +The three +.BR Linux-PAM +Guides, for +.BR "system administrators" ", " +.BR "module developers" ", " +and +.BR "application developers" ". " diff --git a/SOURCES/postlogin.pamd b/SOURCES/postlogin.pamd new file mode 100644 index 0000000..2ce9af4 --- /dev/null +++ b/SOURCES/postlogin.pamd @@ -0,0 +1,8 @@ +#%PAM-1.0 +# This file is auto-generated. +# User changes will be destroyed the next time authselect is run. + +session optional pam_umask.so silent +session [success=1 default=ignore] pam_succeed_if.so service !~ gdm* service !~ su* quiet +session [default=1] pam_lastlog.so nowtmp showfailed +session optional pam_lastlog.so silent noupdate showfailed diff --git a/SOURCES/smartcard-auth.pamd b/SOURCES/smartcard-auth.pamd new file mode 100644 index 0000000..e8a6745 --- /dev/null +++ b/SOURCES/smartcard-auth.pamd @@ -0,0 +1,4 @@ +#%PAM-1.0 +# This file is auto-generated. +# User changes will be destroyed the next time authselect is run. +auth sufficient pam_sss.so allow_missing_name diff --git a/SOURCES/system-auth.5 b/SOURCES/system-auth.5 new file mode 100644 index 0000000..c0ca80b --- /dev/null +++ b/SOURCES/system-auth.5 @@ -0,0 +1,58 @@ +.TH SYSTEM-AUTH 5 "2010 Dec 22" "Red Hat" "Linux-PAM Manual" +.SH NAME + +system-auth \- Common configuration file for PAMified services + +.SH SYNOPSIS +.B /etc/pam.d/system-auth +.B /etc/pam.d/password-auth +.B /etc/pam.d/fingerprint-auth +.B /etc/pam.d/smartcard-auth +.sp 2 +.SH DESCRIPTION + +The purpose of these configuration files are to provide a common +interface for all applications and service daemons calling into +the PAM library. + +.sp +The +.BR system-auth +configuration file is included from nearly all individual service configuration +files with the help of the +.BR substack +directive. + +.sp +The +.BR password-auth +.BR fingerprint-auth +.BR smartcard-auth +configuration files are for applications which handle authentication from +different types of devices via simultaneously running individual conversations +instead of one aggregate conversation. + +.SH NOTES +Previously these common configuration files were included with the help +of the +.BR include +directive. This limited the use of the different action types of modules. +With the use of +.BR substack +directive to include these common configuration files this limitation +no longer applies. + +.SH BUGS +.sp 2 +None known. + +.SH "SEE ALSO" +pam(8), config-util(5), postlogin(5) + +The three +.BR Linux-PAM +Guides, for +.BR "system administrators" ", " +.BR "module developers" ", " +and +.BR "application developers" ". " diff --git a/SOURCES/system-auth.pamd b/SOURCES/system-auth.pamd new file mode 100644 index 0000000..5de6f4d --- /dev/null +++ b/SOURCES/system-auth.pamd @@ -0,0 +1,18 @@ +#%PAM-1.0 +# This file is auto-generated. +# User changes will be destroyed the next time authselect is run. +auth required pam_env.so +auth sufficient pam_unix.so try_first_pass nullok +auth required pam_deny.so + +account required pam_unix.so + +password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= +password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow +password required pam_deny.so + +session optional pam_keyinit.so revoke +session required pam_limits.so +-session optional pam_systemd.so +session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid +session required pam_unix.so diff --git a/SPECS/pam.spec b/SPECS/pam.spec new file mode 100644 index 0000000..c350aeb --- /dev/null +++ b/SPECS/pam.spec @@ -0,0 +1,2324 @@ +%define pam_redhat_version 0.99.11 + +Summary: An extensible library which provides authentication for applications +Name: pam +Version: 1.3.1 +Release: 33%{?dist} +# The library is BSD licensed with option to relicense as GPLv2+ +# - this option is redundant as the BSD license allows that anyway. +# pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+. +License: BSD and GPLv2+ +Group: System Environment/Base +Source0: https://github.com/linux-pam/linux-pam/releases/download/v%{version}/Linux-PAM-%{version}.tar.xz +Source1: https://github.com/linux-pam/linux-pam/releases/download/v%{version}/Linux-PAM-%{version}.tar.xz.asc +Source2: https://releases.pagure.org/pam-redhat/pam-redhat-%{pam_redhat_version}.tar.bz2 +Source5: other.pamd +Source6: system-auth.pamd +Source7: password-auth.pamd +Source8: fingerprint-auth.pamd +Source9: smartcard-auth.pamd +Source10: config-util.pamd +Source11: dlopen.sh +Source12: system-auth.5 +Source13: config-util.5 +Source15: pamtmp.conf +Source16: postlogin.pamd +Source17: postlogin.5 +Source18: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +Patch1: pam-1.2.0-redhat-modules.patch +Patch4: pam-1.1.0-console-nochmod.patch +Patch5: pam-1.1.0-notally.patch +Patch7: pam-1.2.1-faillock.patch +Patch8: pam-1.2.1-faillock-admin-group.patch +Patch9: pam-1.3.1-noflex.patch +Patch10: pam-1.1.3-nouserenv.patch +Patch13: pam-1.1.6-limits-user.patch +Patch15: pam-1.1.8-full-relro.patch +# FIPS related - non upstreamable +Patch20: pam-1.2.0-unix-no-fallback.patch +Patch28: pam-1.1.1-console-errmsg.patch +# Upstreamed partially +Patch29: pam-1.3.0-pwhistory-helper.patch +Patch31: pam-1.1.8-audit-user-mgmt.patch +Patch32: pam-1.2.1-console-devname.patch +Patch33: pam-1.3.0-unix-nomsg.patch +Patch34: pam-1.3.1-coverity.patch +Patch35: pam-1.3.1-console-build.patch +Patch36: pam-1.3.1-faillock-update.patch +Patch37: pam-1.3.1-namespace-mntopts.patch +Patch38: pam-1.3.1-lastlog-no-showfailed.patch +Patch39: pam-1.3.1-lastlog-unlimited-fsize.patch +Patch40: pam-1.3.1-unix-improve-logging.patch +Patch41: pam-1.3.1-tty-audit-manfix.patch +Patch42: pam-1.3.1-fds-closing.patch +Patch43: pam-1.3.1-authtok-verify-fix.patch +Patch44: pam-1.3.1-motd-manpage.patch +# Upstreamed +Patch45: pam-1.3.1-pam-usertype.patch +# Upstreamed +Patch46: pam-1.3.1-audit-error.patch +# Upstreamed +Patch47: pam-1.3.1-pam-modutil-close-write.patch +# https://github.com/linux-pam/linux-pam/commit/6bf9b454eb971083f0cce49faa2aa1cde329ff5d +# https://github.com/linux-pam/linux-pam/commit/9091ea1d81e85f49a221b0325d27b22ce69e444a +# https://github.com/linux-pam/linux-pam/commit/a3a5cbf86083c43026b558e2023f597530626267 +Patch48: pam-1.3.1-wheel-pam_ruser-fallback.patch +# https://github.com/linux-pam/linux-pam/commit/491e5500b6b3913f531574208274358a2df88659 +Patch49: pam-1.3.1-namespace-gdm-doc.patch +# https://github.com/linux-pam/linux-pam/commit/a7453aeeb398d6cbb7a709c4e2a1d75905220fff +Patch50: pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch +# https://github.com/linux-pam/linux-pam/commit/3234488f2c52a021eec87df1990d256314c21bff +Patch51: pam-1.3.1-pam-limits-unlimited-value.patch +# https://github.com/linux-pam/linux-pam/commit/a35e092e24ee7632346a0e1b4a203c04d4cd2c62 +Patch52: pam-1.3.1-pam-keyinit-thread-safe.patch +# https://github.com/linux-pam/linux-pam/commit/f9c9c72121eada731e010ab3620762bcf63db08f +Patch53: pam-1.3.1-pam-motd-support-multiple-motd-paths.patch +# https://github.com/linux-pam/linux-pam/commit/8eaf5570cf011148a0b55c53570df5edaafebdb0 +Patch54: pam-1.3.1-pam-motd-fix-segmentation-fault.patch +# https://github.com/linux-pam/linux-pam/commit/62cd745d730e5ba13d5d7092ac566fc0b2148e61 +Patch55: pam-1.3.1-pam-motd-fix-memory-leak.patch +# Needed by the next patch. Already upstreamed +Patch56: pam-1.3.1-pam-cc-compat.patch +Patch57: pam-1.3.1-inline.patch +# https://github.com/linux-pam/linux-pam/commit/9bcbe96d9e82a23d983c0618178a8dc25596ac2d +# https://github.com/linux-pam/linux-pam/commit/fc867a9e22eac2c9a0ed0577776bba4df21c9aad +Patch58: pam-1.3.1-faillock-load-conf-from-file.patch +# https://github.com/linux-pam/linux-pam/commit/370064ef6f99581b08d473a42bb3417d5dda3e4e +Patch59: pam-1.3.1-pam-usertype-SYS_UID_MAX.patch +# https://github.com/linux-pam/linux-pam/commit/ba2f6dd8b81ea2a58262c1709bec906b6852591d +# https://github.com/linux-pam/linux-pam/commit/1180bde923a22605fe8075cd1fe7992ed7513411 +Patch60: pam-1.3.1-pam-pwhistory-load-conf-from-file.patch +# https://github.com/linux-pam/linux-pam/commit/d57ab22133654033ee1da89f128a81572d320985 +# https://github.com/linux-pam/linux-pam/commit/c2c0434bd634a817f2b16ce7f58fc96c04e88b03 +Patch61: pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch +# https://github.com/linux-pam/linux-pam/commit/40c271164dbcebfc5304d0537a42fb42e6b6803c +Patch62: pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch +# https://github.com/linux-pam/linux-pam/commit/bcbf145ce925934214e48200c27c9ff736452549 +Patch63: pam-1.5.1-pam-faillock-clarify-missing-user.patch +# https://github.com/linux-pam/linux-pam/commit/10086bc69663fa819277af244eeb5b629a2403b8 +Patch64: pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch +# https://github.com/linux-pam/linux-pam/commit/55f206447a1e4ee26e307e7a9c069236e823b1a5 +# https://github.com/linux-pam/linux-pam/commit/80bfda5962e5be3daa70e0fc8c75fc97d1c55121 +Patch65: pam-1.3.1-pam-misc-configurable.patch +# https://github.com/linux-pam/linux-pam/commit/530c9f9e2d746e1d168c6b17863debda7664ac7c +# https://github.com/linux-pam/linux-pam/commit/f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 +Patch66: pam-1.3.1-unix-enable-bcrypt.patch +Patch67: pam-1.3.1-unix-default-rounds.patch +# https://github.com/linux-pam/linux-pam/commit/d54870f993e97fe75e2cd0470a3701d5af22877c +Patch68: pam-1.3.1-faillock-create-tallydir.patch +# https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f +Patch69: pam-1.3.1-access-handle-hostnames.patch +# https://github.com/linux-pam/linux-pam/commit/031bb5a5d0d950253b68138b498dc93be69a64cb +Patch70: pam-1.3.1-namespace-protect-dir.patch + +%define _pamlibdir %{_libdir} +%define _moduledir %{_libdir}/security +%define _secconfdir %{_sysconfdir}/security +%define _pamconfdir %{_sysconfdir}/pam.d + +%if %{?WITH_SELINUX:0}%{!?WITH_SELINUX:1} +%define WITH_SELINUX 1 +%endif +%if %{?WITH_AUDIT:0}%{!?WITH_AUDIT:1} +%define WITH_AUDIT 1 +%endif +%global _performance_build 1 + +Recommends: cracklib-dicts >= 2.8 +Requires: libpwquality >= 0.9.9 +Requires(post): coreutils, /sbin/ldconfig +BuildRequires: autoconf >= 2.60 +BuildRequires: automake, libtool +BuildRequires: bison, flex, sed +BuildRequires: cracklib-devel +BuildRequires: perl-interpreter, pkgconfig, gettext-devel +BuildRequires: libtirpc-devel, libnsl2-devel +%if %{WITH_AUDIT} +BuildRequires: audit-libs-devel >= 1.0.8 +Requires: audit-libs >= 1.0.8 +%endif +%if %{WITH_SELINUX} +BuildRequires: libselinux-devel >= 1.33.2 +Requires: libselinux >= 1.33.2 +%endif +Requires: glibc >= 2.3.90-37 +BuildRequires: libdb-devel +# Following deps are necessary only to build the pam library documentation. +BuildRequires: linuxdoc-tools, elinks, libxslt +BuildRequires: docbook-style-xsl, docbook-dtds + +URL: http://www.linux-pam.org/ + +%description +PAM (Pluggable Authentication Modules) is a system security tool that +allows system administrators to set authentication policy without +having to recompile programs that handle authentication. + +%package devel +Group: Development/Libraries +Summary: Files needed for developing PAM-aware applications and modules for PAM +Requires: pam%{?_isa} = %{version}-%{release} + +%description devel +PAM (Pluggable Authentication Modules) is a system security tool that +allows system administrators to set authentication policy without +having to recompile programs that handle authentication. This package +contains header files used for building both PAM-aware applications +and modules for use with the PAM system. + +%prep +%setup -q -n Linux-PAM-%{version} -a 2 +perl -pi -e "s/ppc64-\*/ppc64-\* \| ppc64p7-\*/" build-aux/config.sub +perl -pi -e "s/\/lib \/usr\/lib/\/lib \/usr\/lib \/lib64 \/usr\/lib64/" m4/libtool.m4 + +# Add custom modules. +mv pam-redhat-%{pam_redhat_version}/* modules + +cp %{SOURCE18} . + +%patch1 -p1 -b .redhat-modules +%patch4 -p1 -b .nochmod +%patch5 -p1 -b .notally +%patch7 -p1 -b .faillock +%patch8 -p1 -b .admin-group +%patch9 -p1 -b .noflex +%patch10 -p1 -b .nouserenv +%patch13 -p1 -b .limits +%patch15 -p1 -b .relro +%patch20 -p1 -b .no-fallback +%patch28 -p1 -b .errmsg +%patch29 -p1 -b .pwhhelper +%patch31 -p1 -b .audit-user-mgmt +%patch32 -p1 -b .devname +%patch33 -p1 -b .nomsg +%patch34 -p1 -b .coverity +%patch35 -p1 -b .console-build +%patch36 -p1 -b .faillock-update +%patch37 -p1 -b .mntopts +%patch38 -p1 -b .no-showfailed +%patch39 -p1 -b .unlimited-fsize +%patch40 -p1 -b .improve-logging +%patch41 -p1 -b .tty-audit-manfix +%patch42 -p1 -b .fds-closing +%patch43 -p1 -b .authtok-verify-fix +%patch44 -p1 -b .motd-manpage +%patch45 -p1 -b .pam-usertype +%patch46 -p1 -b .audit-error +%patch47 -p1 -b .pam-modutil-close-write +%patch48 -p1 -b .wheel-pam_ruser-fallback +%patch49 -p1 -b .namespace-gdm-doc +%patch50 -p1 -b .pam-userdb-prevent-garbage-characters-from-db +%patch51 -p1 -b .pam-limits-unlimited-value +%patch52 -p1 -b .pam-keyinit-thread-safe +%patch53 -p1 -b .pam-motd-support-multiple-motd-paths +%patch54 -p1 -b .pam-motd-fix-segmentation-fault +%patch55 -p1 -b .pam-motd-fix-memory-leak +%patch56 -p1 -b .pam-cc-compat +%patch57 -p1 -b .inline +%patch58 -p1 -b .faillock-load-conf-from-file +%patch59 -p1 -b .pam-usertype-SYS_UID_MAX +%patch60 -p1 -b .pam-pwhistory-load-conf-from-file +%patch61 -p1 -b .pam-motd-avoid-unnecessary-logging +%patch62 -p1 -b .pam-lastlog-check-localtime_r-return-value +%patch63 -p1 -b .pam-faillock-clarify-missing-user +%patch64 -p1 -b .pam-faillock-avoid-logging-erroneous +%patch65 -p1 -b .pam-misc-configurable +%patch66 -p1 -b .unix-enable-bcrypt +%patch67 -p1 -b .unix-default-rounds +%patch68 -p1 -b .faillock-create-tallydir +%patch69 -p1 -b .access-handle-hostnames +%patch70 -p1 -b .namespace-protect-dir + +autoreconf -i + +%build +%configure \ + --disable-rpath \ + --libdir=%{_pamlibdir} \ + --includedir=%{_includedir}/security \ +%if ! %{WITH_SELINUX} + --disable-selinux \ +%endif +%if ! %{WITH_AUDIT} + --disable-audit \ +%endif + --disable-static \ + --disable-prelude +make -C po update-gmo +make +# we do not use _smp_mflags because the build of sources in yacc/flex fails + +%install +mkdir -p doc/txts +for readme in modules/pam_*/README ; do + cp -f ${readme} doc/txts/README.`dirname ${readme} | sed -e 's|^modules/||'` +done + +rm -rf doc/txts/README.pam_tally* +rm -rf doc/sag/html/*pam_tally* + +# Install the binaries, libraries, and modules. +make install DESTDIR=$RPM_BUILD_ROOT LDCONFIG=: + +%if %{WITH_SELINUX} +# Temporary compat link +ln -sf pam_sepermit.so $RPM_BUILD_ROOT%{_moduledir}/pam_selinux_permit.so +%endif + +# RPM uses docs from source tree +rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/Linux-PAM +# Included in setup package +rm -f $RPM_BUILD_ROOT%{_sysconfdir}/environment + +# Install default configuration files. +install -d -m 755 $RPM_BUILD_ROOT%{_pamconfdir} +install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_pamconfdir}/other +install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_pamconfdir}/system-auth +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pamconfdir}/password-auth +install -m 644 %{SOURCE8} $RPM_BUILD_ROOT%{_pamconfdir}/fingerprint-auth +install -m 644 %{SOURCE9} $RPM_BUILD_ROOT%{_pamconfdir}/smartcard-auth +install -m 644 %{SOURCE10} $RPM_BUILD_ROOT%{_pamconfdir}/config-util +install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_pamconfdir}/postlogin +install -m 600 /dev/null $RPM_BUILD_ROOT%{_secconfdir}/opasswd +install -d -m 755 $RPM_BUILD_ROOT/var/log +install -d -m 755 $RPM_BUILD_ROOT/var/run/faillock +install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/motd.d +install -d -m 755 $RPM_BUILD_ROOT/usr/lib/motd.d +install -d -m 755 $RPM_BUILD_ROOT/run/motd.d + +# Install man pages. +install -m 644 %{SOURCE12} %{SOURCE13} %{SOURCE17} $RPM_BUILD_ROOT%{_mandir}/man5/ +ln -sf system-auth.5 $RPM_BUILD_ROOT%{_mandir}/man5/password-auth.5 +ln -sf system-auth.5 $RPM_BUILD_ROOT%{_mandir}/man5/fingerprint-auth.5 +ln -sf system-auth.5 $RPM_BUILD_ROOT%{_mandir}/man5/smartcard-auth.5 + + +for phase in auth acct passwd session ; do + ln -sf pam_unix.so $RPM_BUILD_ROOT%{_moduledir}/pam_unix_${phase}.so +done + +# Remove .la files and make new .so links -- this depends on the value +# of _libdir not changing, and *not* being /usr/lib. +for lib in libpam libpamc libpam_misc ; do +rm -f $RPM_BUILD_ROOT%{_pamlibdir}/${lib}.la +done +rm -f $RPM_BUILD_ROOT%{_moduledir}/*.la + +%if "%{_pamlibdir}" != "%{_libdir}" +install -d -m 755 $RPM_BUILD_ROOT%{_libdir} +for lib in libpam libpamc libpam_misc ; do +pushd $RPM_BUILD_ROOT%{_libdir} +ln -sf %{_pamlibdir}/${lib}.so.*.* ${lib}.so +popd +rm -f $RPM_BUILD_ROOT%{_pamlibdir}/${lib}.so +done +%endif + +# Duplicate doc file sets. +rm -fr $RPM_BUILD_ROOT/usr/share/doc/pam + +# Install the file for autocreation of /var/run subdirectories on boot +install -m644 -D %{SOURCE15} $RPM_BUILD_ROOT%{_prefix}/lib/tmpfiles.d/pam.conf + +%find_lang Linux-PAM + +%check +# Make sure every module subdirectory gave us a module. Yes, this is hackish. +for dir in modules/pam_* ; do +if [ -d ${dir} ] ; then +%if ! %{WITH_SELINUX} + [ ${dir} = "modules/pam_selinux" ] && continue + [ ${dir} = "modules/pam_sepermit" ] && continue +%endif +%if ! %{WITH_AUDIT} + [ ${dir} = "modules/pam_tty_audit" ] && continue +%endif + [ ${dir} = "modules/pam_tally" ] && continue + [ ${dir} = "modules/pam_tally2" ] && continue + if ! ls -1 $RPM_BUILD_ROOT%{_moduledir}/`basename ${dir}`*.so ; then + echo ERROR `basename ${dir}` did not build a module. + exit 1 + fi +fi +done + +# Check for module problems. Specifically, check that every module we just +# installed can actually be loaded by a minimal PAM-aware application. +/sbin/ldconfig -n $RPM_BUILD_ROOT%{_pamlibdir} +for module in $RPM_BUILD_ROOT%{_moduledir}/pam*.so ; do + if ! env LD_LIBRARY_PATH=$RPM_BUILD_ROOT%{_pamlibdir} \ + %{SOURCE11} -ldl -lpam -L$RPM_BUILD_ROOT%{_libdir} ${module} ; then + echo ERROR module: ${module} cannot be loaded. + exit 1 + fi +done + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files -f Linux-PAM.lang +%dir %{_pamconfdir} +%config(noreplace) %{_pamconfdir}/other +%config(noreplace) %{_pamconfdir}/system-auth +%config(noreplace) %{_pamconfdir}/password-auth +%config(noreplace) %{_pamconfdir}/fingerprint-auth +%config(noreplace) %{_pamconfdir}/smartcard-auth +%config(noreplace) %{_pamconfdir}/config-util +%config(noreplace) %{_pamconfdir}/postlogin +%{!?_licensedir:%global license %%doc} +%license Copyright +%license gpl-2.0.txt +%doc doc/txts +%doc doc/sag/*.txt doc/sag/html +%{_pamlibdir}/libpam.so.* +%{_pamlibdir}/libpamc.so.* +%{_pamlibdir}/libpam_misc.so.* +%{_sbindir}/pam_console_apply +%{_sbindir}/faillock +%attr(4755,root,root) %{_sbindir}/pam_timestamp_check +%attr(4755,root,root) %{_sbindir}/unix_chkpwd +%attr(0700,root,root) %{_sbindir}/unix_update +%attr(0755,root,root) %{_sbindir}/mkhomedir_helper +%attr(0755,root,root) %{_sbindir}/pwhistory_helper +%dir %{_moduledir} +%{_moduledir}/pam_access.so +%{_moduledir}/pam_chroot.so +%{_moduledir}/pam_console.so +%{_moduledir}/pam_cracklib.so +%{_moduledir}/pam_debug.so +%{_moduledir}/pam_deny.so +%{_moduledir}/pam_echo.so +%{_moduledir}/pam_env.so +%{_moduledir}/pam_exec.so +%{_moduledir}/pam_faildelay.so +%{_moduledir}/pam_faillock.so +%{_moduledir}/pam_filter.so +%{_moduledir}/pam_ftp.so +%{_moduledir}/pam_group.so +%{_moduledir}/pam_issue.so +%{_moduledir}/pam_keyinit.so +%{_moduledir}/pam_lastlog.so +%{_moduledir}/pam_limits.so +%{_moduledir}/pam_listfile.so +%{_moduledir}/pam_localuser.so +%{_moduledir}/pam_loginuid.so +%{_moduledir}/pam_mail.so +%{_moduledir}/pam_mkhomedir.so +%{_moduledir}/pam_motd.so +%{_moduledir}/pam_namespace.so +%{_moduledir}/pam_nologin.so +%{_moduledir}/pam_permit.so +%{_moduledir}/pam_postgresok.so +%{_moduledir}/pam_pwhistory.so +%{_moduledir}/pam_rhosts.so +%{_moduledir}/pam_rootok.so +%if %{WITH_SELINUX} +%{_moduledir}/pam_selinux.so +%{_moduledir}/pam_selinux_permit.so +%{_moduledir}/pam_sepermit.so +%endif +%{_moduledir}/pam_securetty.so +%{_moduledir}/pam_shells.so +%{_moduledir}/pam_stress.so +%{_moduledir}/pam_succeed_if.so +%{_moduledir}/pam_time.so +%{_moduledir}/pam_timestamp.so +%if %{WITH_AUDIT} +%{_moduledir}/pam_tty_audit.so +%endif +%{_moduledir}/pam_umask.so +%{_moduledir}/pam_unix.so +%{_moduledir}/pam_unix_acct.so +%{_moduledir}/pam_unix_auth.so +%{_moduledir}/pam_unix_passwd.so +%{_moduledir}/pam_unix_session.so +%{_moduledir}/pam_userdb.so +%{_moduledir}/pam_usertype.so +%{_moduledir}/pam_warn.so +%{_moduledir}/pam_wheel.so +%{_moduledir}/pam_xauth.so +%{_moduledir}/pam_filter +%dir %{_secconfdir} +%config(noreplace) %{_secconfdir}/access.conf +%config(noreplace) %{_secconfdir}/chroot.conf +%config %{_secconfdir}/console.perms +%config(noreplace) %{_secconfdir}/console.handlers +%config(noreplace) %{_secconfdir}/faillock.conf +%config(noreplace) %{_secconfdir}/group.conf +%config(noreplace) %{_secconfdir}/limits.conf +%dir %{_secconfdir}/limits.d +%config(noreplace) %{_secconfdir}/namespace.conf +%dir %{_secconfdir}/namespace.d +%attr(755,root,root) %config(noreplace) %{_secconfdir}/namespace.init +%config(noreplace) %{_secconfdir}/pam_env.conf +%config(noreplace) %{_secconfdir}/pwhistory.conf +%config(noreplace) %{_secconfdir}/time.conf +%config(noreplace) %{_secconfdir}/opasswd +%dir %{_secconfdir}/console.apps +%dir %{_secconfdir}/console.perms.d +%dir /var/run/console +%if %{WITH_SELINUX} +%config(noreplace) %{_secconfdir}/sepermit.conf +%dir /var/run/sepermit +%endif +%dir /var/run/faillock +%dir %{_sysconfdir}/motd.d +%dir /run/motd.d +%dir /usr/lib/motd.d +%{_prefix}/lib/tmpfiles.d/pam.conf +%{_mandir}/man5/* +%{_mandir}/man8/* + +%files devel +%{_includedir}/security +%{_mandir}/man3/* +%{_libdir}/libpam.so +%{_libdir}/libpamc.so +%{_libdir}/libpam_misc.so +%doc doc/mwg/*.txt doc/mwg/html +%doc doc/adg/*.txt doc/adg/html +%doc doc/specs/rfc86.0.txt + +%changelog +* Fri Mar 29 2024 MSVSphere Packaging Team - 1.3.1-33 +- Rebuilt for MSVSphere 8.10 beta + +* Mon Feb 12 2024 Iker Pedrosa - 1.3.1-33 +- pam_namespace: protect_dir(): use O_DIRECTORY to prevent local DoS + situations. CVE-2024-22365. Resolves: RHEL-21242 + +* Fri Jan 26 2024 Iker Pedrosa - 1.3.1-32 +- pam_access: handle hostnames in access.conf. Resolves: RHEL-3374 + +* Mon Jan 8 2024 Iker Pedrosa - 1.3.1-31 +- pam_faillock: create tallydir before creating tallyfile. Resolves: RHEL-19810 + +* Thu Nov 2 2023 Iker Pedrosa - 1.3.1-30 +- pam_unix: enable bcrypt. Resolves: RHEL-5057 + +* Mon Jun 26 2023 Iker Pedrosa - 1.3.1-27 +- pam_misc: make length of misc_conv() configurable and set to 4096. Resolves: #2209785 + +* Tue May 16 2023 Iker Pedrosa - 1.3.1-26 +- smartcard-auth: modify the content to remove unnecessary modules. Resolves: #1983683 + +* Tue Nov 29 2022 Iker Pedrosa - 1.3.1-25 +- pam_motd: avoid unnecessary logging. Resolves: #2091062 +- pam_lastlog: check localtime_r() return value. Resolves: #2012871 +- pam_faillock: clarify missing user faillock files after reboot. Resolves: #2062512 +- pam_faillock: avoid logging an erroneous consecutive login failure message. Resolves: #2082442 + +* Thu Sep 29 2022 Iker Pedrosa - 1.3.1-24 +- pam_pwhistory: load configuration from file. Resolves: #2068461 + +* Wed Jul 13 2022 Iker Pedrosa - 1.3.1-22 +- Regenerate the /run/motd.d at each boot. Resolves: #2104878 + +* Thu Jun 23 2022 Iker Pedrosa - 1.3.1-21 +- pam_usertype: only use SYS_UID_MAX for system users. Resolves: #1949137 + +* Thu May 26 2022 Iker Pedrosa - 1.3.1-20 +- faillock: load configuration from file. Resolves: #1978029 + +* Mon May 23 2022 Iker Pedrosa - 1.3.1-19 +- Add the motd.d directories (empty) to silence warnings and to + provide proper ownership for them. Resolves: #2014458 + +* Thu May 19 2022 Iker Pedrosa - 1.3.1-18 +- pam_motd: fix memory leak. Resolves: #2014458 + +* Tue May 17 2022 Iker Pedrosa - 1.3.1-17 +- pam_keyinit: thread-safe implementation. Resolves: #1997969 +- pam_motd: support multiple motd paths specified, with filename overrides. Resolves: #2014458 + +* Fri Jan 28 2022 Iker Pedrosa - 1.3.1-16 +- pam_limits: "Unlimited" is not a valid value for RLIMIT_NOFILE. Resolves: #2047655 + +* Mon May 3 2021 Iker Pedrosa 1.3.1-15 +- pam_userdb: Prevent garbage characters from db (#1791965) + +* Thu Nov 5 2020 Iker Pedrosa 1.3.1-14 +- Revert 1.3.1-12 + +* Fri Oct 30 2020 Iker Pedrosa 1.3.1-13 +- pam_wheel: if getlogin fails fallback to PAM_RUSER: fixed malformed patch (#1866866) +- pam_namespace: polyinstantiation refer to gdm doc (#1861841) + +* Thu Jul 16 2020 Peter Robinson - 1.3.1-12 +- Add the motd.d directories (empty) to silence warnings and to + provide proper ownership for them (#1847501) + +* Fri May 15 2020 Iker Pedrosa 1.3.1-11 +- pam_usertype: fixed malformed patch + +* Tue Apr 21 2020 Iker Pedrosa 1.3.1-10 +- pam_modutil_sanitize_helper_fds: fix SIGPIPE effect of PAM_MODUTIL_PIPE_FD (#1791970) + +* Fri Apr 17 2020 Iker Pedrosa 1.3.1-9 +- pam_usertype: new module to tell if uid is in login.defs ranges (#1810474) +- pam_tty_audit: if kernel audit is disabled return PAM_IGNORE (#1775357) + +* Thu Dec 19 2019 Tomáš Mráz 1.3.1-8 +- pam_motd: Document how to properly silence unwanted motd messages + +* Mon Dec 16 2019 Tomáš Mráz 1.3.1-6 +- pam_faillock: Fix regression in admin_group support + +* Wed Oct 16 2019 Tomáš Mráz 1.3.1-5 +- pam_faillock: Support configuration file /etc/security/faillock.conf +- pam_faillock: Support local_users_only option +- pam_namespace: Support noexec, nosuid and nodev flags for tmpfs mounts +- Drop tallylog and pam_tally[2] documentation +- pam_lastlog: Do not display failed attempts with PAM_SILENT flag +- pam_lastlog: Support unlimited option to override fsize limit +- pam_unix: Log if user authenticated without password +- pam_tty_audit: Improve manual page +- Optimize closing fds when spawning helpers +- Fix duplicate password verification in pam_authtok_verify() + +* Fri Dec 7 2018 Tomáš Mráz 1.3.1-4 +- Drop pam_tally2 which was obsoleted and deprecated long time ago + +* Mon Sep 10 2018 Tomáš Mráz 1.3.1-3 +- add pam_umask to postlogin PAM configuration file +- fix some issues found by Coverity scan + +* Fri Jun 8 2018 Tomáš Mráz 1.3.1-1 +- use /run instead of /var/run in pamtmp.conf (#1588612) + +* Fri May 18 2018 Tomáš Mráz 1.3.1-1 +- new upstream release 1.3.1 with multiple improvements + +* Thu Feb 08 2018 Fedora Release Engineering - 1.3.0-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Tue Jan 30 2018 Tomáš Mráz 1.3.0-9 +- and the NIS support now also requires libnsl2 + +* Sat Jan 20 2018 Björn Esser - 1.3.0-8 +- Rebuilt for switch to libxcrypt + +* Thu Jan 11 2018 Tomáš Mráz 1.3.0-7 +- the NIS support now requires libtirpc + +* Mon Aug 21 2017 Tomáš Mráz 1.3.0-6 +- add admin_group option to pam_faillock (#1285550) + +* Thu Aug 03 2017 Fedora Release Engineering - 1.3.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 1.3.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Apr 20 2017 Tomáš Mráz 1.3.0-3 +- drop superfluous 'Changing password' message from pam_unix (#658289) + +* Sat Feb 11 2017 Fedora Release Engineering - 1.3.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri May 6 2016 Tomáš Mráz 1.3.0-1 +- new upstream release with multiple improvements + +* Mon Apr 11 2016 Tomáš Mráz 1.2.1-8 +- make cracklib-dicts dependency weak (#1323172) + +* Wed Apr 6 2016 Tomáš Mráz 1.2.1-7 +- do not drop PAM_OLDAUTHTOK if mismatched - can be used by further modules + +* Mon Apr 4 2016 Tomáš Mráz 1.2.1-6 +- pam_unix: use pam_get_authtok() and improve prompting + +* Fri Feb 5 2016 Tomáš Mráz 1.2.1-5 +- fix console device name in console.handlers (#1270224) + +* Thu Feb 04 2016 Fedora Release Engineering - 1.2.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Oct 16 2015 Tomáš Mráz 1.2.1-3 +- pam_faillock: add possibility to set unlock_time to never + +* Wed Aug 12 2015 Tomáš Mráz 1.2.1-2 +- drop the nproc limit setting, it is causing more harm than it solves + +* Fri Jun 26 2015 Tomáš Mráz 1.2.1-1 +- new upstream release fixing security issue with unlimited password length + +* Thu Jun 18 2015 Fedora Release Engineering - 1.2.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Fri May 15 2015 Tomáš Mráz 1.2.0-1 +- new upstream release with multiple minor improvements + +* Fri Oct 17 2014 Tomáš Mráz 1.1.8-18 +- use USER_MGMT type for auditing in the pam_tally2 and faillock + apps (#1151576) + +* Thu Sep 11 2014 Tomáš Mráz 1.1.8-17 +- update the audit-grantor patch with the upstream changes +- pam_userdb: correct the example in man page (#1078784) +- pam_limits: check whether the utmp login entry is valid (#1080023) +- pam_console_apply: do not print error if console.perms.d is empty +- pam_limits: nofile refers to open file descriptors (#1111220) +- apply PIE and full RELRO to all binaries built + +* Sun Aug 17 2014 Fedora Release Engineering - 1.1.8-16 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Aug 13 2014 Tomáš Mráz 1.1.8-15 +- audit the module names that granted access +- pam_faillock: update to latest version + +* Wed Jul 30 2014 Tom Callaway - 1.1.8-14 +- fix license handling + +* Wed Jul 16 2014 Tomáš Mráz 1.1.8-13 +- be tolerant to corrupted opasswd file + +* Fri Jun 06 2014 Fedora Release Engineering - 1.1.8-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu May 22 2014 Tomáš Mráz 1.1.8-11 +- pam_loginuid: make it return PAM_IGNORE in containers + +* Mon Mar 31 2014 Tomáš Mráz 1.1.8-10 +- fix CVE-2014-2583: potential path traversal issue in pam_timestamp + +* Wed Mar 26 2014 Tomáš Mráz 1.1.8-9 +- pam_pwhistory: call the helper if SELinux enabled + +* Tue Mar 11 2014 Tomáš Mráz 1.1.8-8 +- fix CVE-2013-7041: use case sensitive comparison in pam_userdb + +* Mon Mar 10 2014 Tomáš Mráz 1.1.8-7 +- rename the 90-nproc.conf to 20-nproc.conf (#1071618) +- canonicalize user name in pam_selinux (#1071010) +- refresh the pam-redhat tarball + +* Mon Dec 16 2013 Tomáš Mráz 1.1.8-4 +- raise the default soft nproc limit to 4096 + +* Mon Dec 2 2013 Tomáš Mráz 1.1.8-3 +- updated translations + +* Mon Oct 21 2013 Tomáš Mráz 1.1.8-2 +- update lastlog with pam_lastlog also for su (#1021108) + +* Mon Oct 14 2013 Tomáš Mráz 1.1.8-1 +- new upstream release +- pam_tty_audit: allow the module to work with old kernels + +* Fri Oct 4 2013 Tomáš Mráz 1.1.7-3 +- pam_tty_audit: proper initialization of the tty_audit_status struct + +* Mon Sep 30 2013 Tomáš Mráz 1.1.7-2 +- add "local_users_only" to pam_pwquality in default configuration + +* Fri Sep 13 2013 Tomáš Mráz 1.1.7-1 +- new upstream release + +* Wed Aug 7 2013 Tomáš Mráz 1.1.6-14 +- use links instead of w3m to create txt documentation +- recognize login session in pam_sepermit to prevent gdm from locking (#969174) +- add support for disabling password logging in pam_tty_audit + +* Sat Aug 03 2013 Fedora Release Engineering - 1.1.6-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Thu Jul 11 2013 Tomáš Mráz 1.1.6-12 +- add auditing of SELinux policy violation in pam_rootok (#965723) +- add SELinux helper to pam_pwhistory + +* Tue May 7 2013 Tomáš Mráz 1.1.6-11 +- the default isadir is more correct + +* Wed Apr 24 2013 Tomáš Mráz 1.1.6-10 +- pam_unix: do not fail with bad ld.so.preload + +* Fri Mar 22 2013 Tomáš Mráz 1.1.6-9 +- do not fail if btmp file is corrupted (#906852) +- fix strict aliasing warnings in build +- UsrMove +- use authtok_type with pam_pwquality in system-auth +- remove manual_context handling from pam_selinux (#876976) +- other minor specfile cleanups + +* Tue Mar 19 2013 Tomáš Mráz 1.1.6-8 +- check NULL return from crypt() calls (#915316) + +* Thu Mar 14 2013 Tomáš Mráz 1.1.6-7 +- add workaround for low nproc limit for confined root user (#432903) + +* Thu Feb 21 2013 Karsten Hopp 1.1.6-6 +- add support for ppc64p7 arch (Power7 optimized) + +* Thu Feb 14 2013 Fedora Release Engineering - 1.1.6-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Jan 22 2013 Tomas Mraz 1.1.6-4 +- fix build with current autotools + +* Mon Oct 15 2012 Tomas Mraz 1.1.6-3 +- add support for tmpfs mount options in pam_namespace + +* Mon Sep 3 2012 Tomas Mraz 1.1.6-2 +- link setuid binaries with full relro (#853158) +- add rhost and tty to auditing data in modules (#677664) + +* Fri Aug 17 2012 Tomas Mraz - 1.1.6-1 +- new upstream release + +* Thu Aug 9 2012 Tomas Mraz - 1.1.5-9 +- make the pam_lastlog module in postlogin 'optional' (#846843) + +* Mon Aug 6 2012 Tomas Mraz - 1.1.5-8 +- fix build failure in pam_unix +- add display of previous bad login attempts to postlogin.pamd +- put the tmpfiles.d config to /usr/lib and rename it to pam.conf +- build against libdb-5 + +* Wed May 9 2012 Tomas Mraz 1.1.5-7 +- add inactive account lock out functionality to pam_lastlog +- fix pam_unix remember user name matching +- add gecoscheck and maxclassrepeat functionality to pam_cracklib +- correctly check for crypt() returning NULL in pam_unix +- pam_unix - do not fallback to MD5 on password change + if requested algorithm not supported by crypt() (#818741) +- install empty directories + +* Wed May 9 2012 Tomas Mraz 1.1.5-6 +- add pam_systemd to session modules + +* Tue Jan 31 2012 Tomas Mraz 1.1.5-5 +- fix pam_namespace leaking the protect mounts to parent namespace (#755216) + +* Fri Jan 13 2012 Fedora Release Engineering - 1.1.5-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Dec 21 2011 Tomas Mraz 1.1.5-3 +- add a note to limits.conf (#754285) + +* Thu Nov 24 2011 Tomas Mraz 1.1.5-2 +- use pam_pwquality instead of pam_cracklib + +* Thu Nov 24 2011 Tomas Mraz 1.1.5-1 +- upgrade to new upstream release + +* Thu Aug 25 2011 Tomas Mraz 1.1.4-4 +- fix dereference in pam_env +- fix wrong parse of user@host pattern in pam_access (#732081) + +* Sat Jul 23 2011 Ville Skyttä - 1.1.4-3 +- Rebuild to fix trailing slashes in provided dirs added by rpm 4.9.1. + +* Fri Jul 15 2011 Tomas Mraz 1.1.4-2 +- clear supplementary groups in pam_console handler execution + +* Mon Jun 27 2011 Tomas Mraz 1.1.4-1 +- upgrade to new upstream release + +* Tue Jun 7 2011 Tomas Mraz 1.1.3-10 +- detect the shared / and make the polydir mounts private based on that +- fix memory leak and other small errors in pam_namespace + +* Thu Jun 2 2011 Tomas Mraz 1.1.3-9 +- add support for explicit marking of the polydir mount private (#623522) + +* Tue Feb 08 2011 Fedora Release Engineering - 1.1.3-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Dec 22 2010 Tomas Mraz 1.1.3-7 +- add postlogin common PAM configuration file (#665059) + +* Tue Dec 14 2010 Tomas Mraz 1.1.3-6 +- include patches recently submitted and applied to upstream CVS + +* Thu Nov 25 2010 Tomas Mraz 1.1.3-5 +- add config for autocreation of subdirectories in /var/run (#656655) +- automatically enable kernel console in pam_securetty + +* Wed Nov 10 2010 Tomas Mraz 1.1.3-4 +- fix memory leak in pam_faillock + +* Wed Nov 10 2010 Tomas Mraz 1.1.3-3 +- fix segfault in faillock utility +- remove some cases where the information of existence of + an user account could be leaked by the pam_faillock, + document the remaining case + +* Fri Nov 5 2010 Tomas Mraz 1.1.3-2 +- fix a mistake in the abstract X-socket connect +- make pam_faillock work with screensaver + +* Mon Nov 1 2010 Tomas Mraz 1.1.3-1 +- upgrade to new upstream release fixing CVE-2010-3316 CVE-2010-3435 + CVE-2010-3853 +- try to connect to an abstract X-socket first to verify we are + at real console (#647191) + +* Wed Sep 29 2010 jkeating - 1.1.2-2 +- Rebuilt for gcc bug 634757 + +* Mon Sep 20 2010 Tomas Mraz 1.1.2-1 +- add pam_faillock module implementing temporary account lock out based + on authentication failures during a specified interval +- do not build some auxiliary tools that are not installed that require + flex-static to build +- upgrade to new upstream release + +* Thu Jul 15 2010 Tomas Mraz 1.1.1-5 +- do not overwrite tallylog with empty file on upgrade + +* Mon Feb 15 2010 Tomas Mraz 1.1.1-4 +- change the default password hash to sha512 + +* Fri Jan 22 2010 Tomas Mraz 1.1.1-3 +- fix wrong prompt when pam_get_authtok is used for new password + +* Mon Jan 18 2010 Tomas Mraz 1.1.1-2 +- fix build with disabled audit and SELinux (#556211, #556212) + +* Thu Dec 17 2009 Tomas Mraz 1.1.1-1 +- new upstream version with minor changes + +* Mon Nov 2 2009 Tomas Mraz 1.1.0-7 +- pam_console: fix memory corruption when executing handlers (patch by + Stas Sergeev) and a few more fixes in the handler execution code (#532302) + +* Thu Oct 29 2009 Tomas Mraz 1.1.0-6 +- pam_xauth: set the approprate context when creating .xauth files (#531530) + +* Tue Sep 1 2009 Tomas Mraz 1.1.0-5 +- do not change permissions with pam_console_apply +- drop obsolete pam_tally module and the faillog file (#461258) + +* Wed Aug 19 2009 Tomas Mraz 1.1.0-4 +- rebuild with new libaudit + +* Mon Jul 27 2009 Tomas Mraz 1.1.0-3 +- fix for pam_cracklib from upstream + +* Sat Jul 25 2009 Fedora Release Engineering - 1.1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jun 23 2009 Tomas Mraz 1.1.0-1 +- update to new upstream version + +* Wed May 13 2009 Tomas Mraz 1.0.92-1 +- update to new upstream version + +* Fri Apr 10 2009 Tomas Mraz 1.0.91-6 +- add password-auth, fingerprint-auth, and smartcard-auth + for applications which can use them namely gdm (#494874) + patch by Ray Strode + +* Thu Mar 26 2009 Tomas Mraz 1.0.91-5 +- replace also other std descriptors (#491471) + +* Tue Mar 17 2009 Tomas Mraz 1.0.91-3 +- we must replace the stdin when execing the helper (#490644) + +* Mon Mar 16 2009 Tomas Mraz 1.0.91-2 +- do not close stdout/err when execing the helpers (#488147) + +* Mon Mar 9 2009 Tomas Mraz 1.0.91-1 +- upgrade to new upstream release + +* Fri Feb 27 2009 Tomas Mraz 1.0.90-4 +- fix parsing of config files containing non-ASCII characters +- fix CVE-2009-0579 (mininimum days for password change ignored) (#487216) +- pam_access: improve handling of hostname resolution + +* Thu Feb 26 2009 Fedora Release Engineering - 1.0.90-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Mon Jan 19 2009 Tomas Mraz 1.0.90-2 +- add helper to pam_mkhomedir for proper SELinux confinement (#476784) + +* Tue Dec 16 2008 Tomas Mraz 1.0.90-1 +- upgrade to new upstream release +- add --disable-prelude (#466242) + +* Tue Sep 23 2008 Tomas Mraz 1.0.2-2 +- new password quality checks in pam_cracklib +- report failed logins from btmp in pam_lastlog +- allow larger groups in modutil functions +- fix leaked file descriptor in pam_tally + +* Mon Sep 8 2008 Tomas Mraz 1.0.2-1 +- pam_loginuid: uids are unsigned (#460241) +- new minor upstream release +- use external db4 +- drop tests for not pulling in libpthread (as NPTL should + be safe) + +* Wed Jul 9 2008 Tomas Mraz 1.0.1-5 +- update internal db4 + +* Wed May 21 2008 Tomas Mraz 1.0.1-4 +- pam_namespace: allow safe creation of directories owned by user (#437116) +- pam_unix: fix multiple error prompts on password change (#443872) + +* Tue May 20 2008 Tomas Mraz 1.0.1-3 +- pam_selinux: add env_params option which will be used by OpenSSH +- fix build with new autoconf + +* Tue Apr 22 2008 Tomas Mraz 1.0.1-2 +- pam_selinux: restore execcon properly (#443667) + +* Fri Apr 18 2008 Tomas Mraz 1.0.1-1 +- upgrade to new upstream release (one bugfix only) +- fix pam_sepermit use in screensavers + +* Mon Apr 7 2008 Tomas Mraz 1.0.0-2 +- fix regression in pam_set_item + +* Fri Apr 4 2008 Tomas Mraz 1.0.0-1 +- upgrade to new upstream release (bugfix only) + +* Thu Mar 20 2008 Tomas Mraz 0.99.10.0-4 +- pam_namespace: fix problem with level polyinst (#438264) +- pam_namespace: improve override checking for umount +- pam_selinux: fix syslogging a context after free() (#438338) + +* Thu Feb 28 2008 Tomas Mraz 0.99.10.0-3 +- update pam-redhat module tarball +- update internal db4 + +* Fri Feb 22 2008 Tomas Mraz 0.99.10.0-2 +- if shadow is readable for an user do not prevent him from + authenticating any user with unix_chkpwd (#433459) +- call audit from unix_chkpwd when appropriate + +* Fri Feb 15 2008 Tomas Mraz 0.99.10.0-1 +- new upstream release +- add default soft limit for nproc of 1024 to prevent + accidental fork bombs (#432903) + +* Mon Feb 4 2008 Tomas Mraz 0.99.8.1-18 +- allow the package to build without SELinux and audit support (#431415) +- macro usage cleanup + +* Mon Jan 28 2008 Tomas Mraz 0.99.8.1-17 +- test for setkeycreatecon correctly +- add exclusive login mode of operation to pam_selinux_permit (original + patch by Dan Walsh) + +* Tue Jan 22 2008 Tomas Mraz 0.99.8.1-16 +- add auditing to pam_access, pam_limits, and pam_time +- moved sanity testing code to check script + +* Mon Jan 14 2008 Tomas Mraz 0.99.8.1-15 +- merge review fixes (#226228) + +* Tue Jan 8 2008 Tomas Mraz 0.99.8.1-14 +- support for sha256 and sha512 password hashes +- account expiry checks moved to unix_chkpwd helper + +* Wed Jan 2 2008 Tomas Mraz 0.99.8.1-13 +- wildcard match support in pam_tty_audit (by Miloslav Trmač) + +* Thu Nov 29 2007 Tomas Mraz 0.99.8.1-12 +- add pam_tty_audit module (#244352) - written by Miloslav Trmač + +* Wed Nov 7 2007 Tomas Mraz 0.99.8.1-11 +- add substack support + +* Tue Sep 25 2007 Tomas Mraz 0.99.8.1-10 +- update db4 to 4.6.19 (#274661) + +* Fri Sep 21 2007 Tomas Mraz 0.99.8.1-9 +- do not preserve contexts when copying skel and other namespace.init + fixes (#298941) +- do not free memory sent to putenv (#231698) + +* Wed Sep 19 2007 Tomas Mraz 0.99.8.1-8 +- add pam_selinux_permit module +- pam_succeed_if: fix in operator (#295151) + +* Tue Sep 18 2007 Tomas Mraz 0.99.8.1-7 +- when SELinux enabled always run the helper binary instead of + direct shadow access (#293181) + +* Fri Aug 24 2007 Tomas Mraz 0.99.8.1-6 +- do not ask for blank password when SELinux confined (#254044) +- initialize homedirs in namespace init script (original patch by dwalsh) + +* Wed Aug 22 2007 Tomas Mraz 0.99.8.1-5 +- most devices are now handled by HAL and not pam_console (patch by davidz) +- license tag fix +- multifunction scanner device support (#251468) + +* Mon Aug 13 2007 Tomas Mraz 0.99.8.1-4 +- fix auth regression when uid != 0 from previous build (#251804) + +* Mon Aug 6 2007 Tomas Mraz 0.99.8.1-3 +- updated db4 to 4.6.18 (#249740) +- added user and new instance parameters to namespace init +- document the new features of pam_namespace +- do not log an audit error when uid != 0 (#249870) + +* Wed Jul 25 2007 Jeremy Katz - 0.99.8.1-2 +- rebuild for toolchain bug + +* Mon Jul 23 2007 Tomas Mraz 0.99.8.1-1 +- upgrade to latest upstream version +- add some firewire devices to default console perms (#240770) + +* Thu Apr 26 2007 Tomas Mraz 0.99.7.1-6 +- pam_namespace: better document behavior on failure (#237249) +- pam_unix: split out passwd change to a new helper binary (#236316) +- pam_namespace: add support for temporary logons (#241226) + +* Fri Apr 13 2007 Tomas Mraz 0.99.7.1-5 +- pam_selinux: improve context change auditing (#234781) +- pam_namespace: fix parsing config file with unknown users (#234513) + +* Fri Mar 23 2007 Tomas Mraz 0.99.7.1-4 +- pam_console: always decrement use count (#230823) +- pam_namespace: use raw context for poly dir name (#227345) +- pam_namespace: truncate long poly dir name (append hash) (#230120) +- we don't patch any po files anymore + +* Wed Feb 21 2007 Tomas Mraz 0.99.7.1-3 +- correctly relabel tty in the default case (#229542) +- pam_unix: cleanup of bigcrypt support +- pam_unix: allow modification of '*' passwords to root + +* Tue Feb 6 2007 Tomas Mraz 0.99.7.1-2 +- more X displays as consoles (#227462) + +* Wed Jan 24 2007 Tomas Mraz 0.99.7.1-1 +- upgrade to new upstream version resolving CVE-2007-0003 +- pam_namespace: unmount poly dir for override users + +* Mon Jan 22 2007 Tomas Mraz 0.99.7.0-2 +- add back min salt length requirement which was erroneously removed + upstream (CVE-2007-0003) + +* Fri Jan 19 2007 Tomas Mraz 0.99.7.0-1 +- upgrade to new upstream version +- drop pam_stack module as it is obsolete +- some changes to silence rpmlint + +* Tue Jan 16 2007 Tomas Mraz 0.99.6.2-8 +- properly include /var/log/faillog and tallylog as ghosts + and create them in post script (#209646) +- update gmo files as we patch some po files (#218271) +- add use_current_range option to pam_selinux (#220487) +- improve the role selection in pam_selinux +- remove shortcut on Password: in ja locale (#218271) +- revert to old euid and not ruid when setting euid in pam_keyinit (#219486) +- rename selinux-namespace patch to namespace-level + +* Fri Dec 1 2006 Dan Walsh 0.99.6.2-7 +- fix selection of role + +* Fri Dec 1 2006 Dan Walsh 0.99.6.2-6 +- add possibility to pam_namespace to only change MLS component +- Resolves: Bug #216184 + +* Thu Nov 30 2006 Tomas Mraz 0.99.6.2-5 +- add select-context option to pam_selinux (#213812) +- autoreconf won't work with autoconf-2.61 as configure.in is not yet adjusted + for it + +* Mon Nov 13 2006 Tomas Mraz 0.99.6.2-4 +- update internal db4 to 4.5.20 version +- move setgid before setuid in pam_keyinit (#212329) +- make username check in pam_unix consistent with useradd (#212153) + +* Tue Oct 24 2006 Tomas Mraz 0.99.6.2-3.3 +- don't overflow a buffer in pam_namespace (#211989) + +* Mon Oct 16 2006 Tomas Mraz 0.99.6.2-3.2 +- /var/log/faillog and tallylog must be config(noreplace) + +* Fri Oct 13 2006 Tomas Mraz 0.99.6.2-3.1 +- preserve effective uid in namespace.init script (LSPP for newrole) +- include /var/log/faillog and tallylog to filelist (#209646) +- add ids to .xml docs so the generated html is always the same (#210569) + +* Thu Sep 28 2006 Tomas Mraz 0.99.6.2-3 +- add pam_namespace option no_unmount_on_close, required for newrole + +* Mon Sep 4 2006 Tomas Mraz 0.99.6.2-2 +- silence pam_succeed_if in default system-auth (#205067) +- round the pam_timestamp_check sleep up to wake up at the start of the + wallclock second (#205068) + +* Thu Aug 31 2006 Tomas Mraz 0.99.6.2-1 +- upgrade to new upstream version, as there are mostly bugfixes except + improved documentation +- add support for session and password service for pam_access and + pam_succeed_if +- system-auth: skip session pam_unix for crond service + +* Thu Aug 10 2006 Dan Walsh 0.99.5.0-8 +- Add new setkeycreatecon call to pam_selinux to make sure keyring has correct context + +* Thu Aug 10 2006 Tomas Mraz 0.99.5.0-7 +- revoke keyrings properly when pam_keyinit called as root (#201048) +- pam_succeed_if should return PAM_USER_UNKNOWN when getpwnam fails (#197748) + +* Wed Aug 2 2006 Tomas Mraz 0.99.5.0-6 +- revoke keyrings properly when pam_keyinit called more than once (#201048) + patch by David Howells + +* Fri Jul 21 2006 Tomas Mraz 0.99.5.0-5 +- don't log pam_keyinit debug messages by default (#199783) + +* Fri Jul 21 2006 Tomas Mraz 0.99.5.0-4 +- drop ainit from console.handlers (#199561) + +* Mon Jul 17 2006 Tomas Mraz 0.99.5.0-3 +- don't report error in pam_selinux for nonexistent tty (#188722) +- add pam_keyinit to the default system-auth file (#198623) + +* Wed Jul 12 2006 Jesse Keating - 0.99.5.0-2.1 +- rebuild + +* Mon Jul 3 2006 Tomas Mraz 0.99.5.0-2 +- fixed network match in pam_access (patch by Dan Yefimov) + +* Fri Jun 30 2006 Tomas Mraz 0.99.5.0-1 +- updated to a new upstream release +- added service as value to be matched and list matching to + pam_succeed_if +- namespace.init was missing from EXTRA_DIST + +* Thu Jun 8 2006 Tomas Mraz 0.99.4.0-5 +- updated pam_namespace with latest patch by Janak Desai +- merged pam_namespace patches +- added buildrequires libtool +- fixed a few rpmlint warnings + +* Wed May 24 2006 Tomas Mraz 0.99.4.0-4 +- actually don't link to libssl as it is not used (#191915) + +* Wed May 17 2006 Tomas Mraz 0.99.4.0-3 +- use md5 implementation from pam_unix in pam_namespace +- pam_namespace should call setexeccon only when selinux is enabled + +* Tue May 16 2006 Tomas Mraz 0.99.4.0-2 +- pam_console_apply shouldn't access /var when called with -r (#191401) +- actually apply the large-uid patch +- don't build hmactest in pam_timestamp so openssl-devel is not required +- add missing buildrequires (#191915) + +* Wed May 10 2006 Tomas Mraz 0.99.4.0-1 +- upgrade to new upstream version +- make pam_console_apply not dependent on glib +- support large uids in pam_tally, pam_tally2 + +* Thu May 4 2006 Tomas Mraz 0.99.3.0-5 +- the namespace instance init script is now in /etc/security (#190148) +- pam_namespace: added missing braces (#190026) +- pam_tally(2): never call fclose twice on the same FILE (from upstream) + +* Wed Apr 26 2006 Tomas Mraz 0.99.3.0-4 +- fixed console device class for irda (#189966) +- make pam_console_apply fail gracefully when a class is missing + +* Tue Apr 25 2006 Tomas Mraz 0.99.3.0-3 +- added pam_namespace module written by Janak Desai (per-user /tmp +support) +- new pam-redhat modules version + +* Fri Feb 24 2006 Tomas Mraz 0.99.3.0-2 +- added try_first_pass option to pam_cracklib +- use try_first_pass for pam_unix and pam_cracklib in + system-auth (#182350) + +* Fri Feb 10 2006 Jesse Keating - 0.99.3.0-1.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 0.99.3.0-1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Fri Feb 3 2006 Tomas Mraz 0.99.3.0-1 +- new upstream version +- updated db4 to 4.3.29 +- added module pam_tally2 with auditing support +- added manual pages for system-auth and config-util (#179584) + +* Tue Jan 3 2006 Tomas Mraz 0.99.2.1-3 +- remove 'initscripts' dependency (#176508) +- update pam-redhat modules, merged patches + +* Fri Dec 16 2005 Tomas Mraz 0.99.2.1-2 +- fix dangling symlinks in -devel (#175929) +- link libaudit only where necessary +- actually compile in audit support + +* Thu Dec 15 2005 Tomas Mraz 0.99.2.1-1 +- support netgroup matching in pam_succeed_if +- upgrade to new release +- drop pam_pwdb as it was obsolete long ago +- we don't build static libraries anymore + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Tue Nov 15 2005 Tomas Mraz 0.80-14 +- pam_stack is deprecated - log its usage + +* Wed Oct 26 2005 Tomas Mraz 0.80-13 +- fixed CAN-2005-2977 unix_chkpwd should skip user verification only if + run as root (#168181) +- link pam_loginuid to libaudit +- support no tty in pam_access (#170467) +- updated audit patch (by Steve Grubb) +- the previous pam_selinux change was not applied properly +- pam_xauth: look for the xauth binary in multiple directories (#171164) + +* Wed Oct 26 2005 Dan Walsh 0.80-12 +- Eliminate multiple in pam_selinux + +* Fri Oct 14 2005 Dan Walsh 0.80-11 +- Eliminate fail over for getseuserbyname call + +* Thu Oct 13 2005 Dan Walsh 0.80-10 +- Add getseuserbyname call for SELinux MCS/MLS policy + +* Tue Oct 4 2005 Tomas Mraz +- pam_console manpage fixes (#169373) + +* Fri Sep 30 2005 Tomas Mraz 0.80-9 +- don't include ps and pdf docs (#168823) +- new common config file for configuration utilities +- remove glib2 dependency (#166979) + +* Tue Sep 20 2005 Tomas Mraz 0.80-8 +- process limit values other than RLIMIT_NICE correctly (#168790) +- pam_unix: always honor nis flag on password change (by Aaron Hope) + +* Wed Aug 24 2005 Tomas Mraz 0.80-7 +- don't fail in audit code when audit is not compiled in + on the newest kernels (#166422) + +* Mon Aug 01 2005 Tomas Mraz 0.80-6 +- add option to pam_loginuid to require auditd + +* Fri Jul 29 2005 Tomas Mraz 0.80-5 +- fix NULL dereference in pam_userdb (#164418) + +* Tue Jul 26 2005 Tomas Mraz 0.80-4 +- fix 64bit bug in pam_pwdb +- don't crash in pam_unix if pam_get_data fail + +* Fri Jul 22 2005 Tomas Mraz 0.80-3 +- more pam_selinux permissive fixes (Dan Walsh) +- make binaries PIE (#158938) + +* Mon Jul 18 2005 Tomas Mraz 0.80-2 +- fixed module tests so the pam doesn't require itself to build (#163502) +- added buildprereq for building the documentation (#163503) +- relaxed permissions of binaries (u+w) + +* Thu Jul 14 2005 Tomas Mraz 0.80-1 +- upgrade to new upstream sources +- removed obsolete patches +- pam_selinux module shouldn't fail on broken configs unless + policy is set to enforcing (Dan Walsh) + +* Tue Jun 21 2005 Tomas Mraz 0.79-11 +- update pam audit patch +- add support for new limits in kernel-2.6.12 (#157050) + +* Thu Jun 9 2005 Tomas Mraz 0.79-10 +- add the Requires dependency on audit-libs (#159885) +- pam_loginuid shouldn't report error when /proc/self/loginuid + is missing (#159974) + +* Fri May 20 2005 Tomas Mraz 0.79-9 +- update the pam audit patch to support newest audit library, + audit also pam_setcred calls (Steve Grubb) +- don't use the audit_fd as global static variable +- don't unset the XAUTHORITY when target user is root + +* Mon May 2 2005 Tomas Mraz 0.79-8 +- pam_console: support loading .perms files in the console.perms.d (#156069) + +* Tue Apr 26 2005 Tomas Mraz 0.79-7 +- pam_xauth: unset the XAUTHORITY variable on error, fix + potential memory leaks +- modify path to IDE floppy devices in console.perms (#155560) + +* Sat Apr 16 2005 Steve Grubb 0.79-6 +- Adjusted pam audit patch to make exception for ECONNREFUSED + +* Tue Apr 12 2005 Tomas Mraz 0.79-5 +- added auditing patch by Steve Grubb +- added cleanup patches for bugs found by Steve Grubb +- don't clear the shadow option of pam_unix if nis option used + +* Fri Apr 8 2005 Tomas Mraz 0.79-4 +- #150537 - flush input first then write the prompt + +* Thu Apr 7 2005 Tomas Mraz 0.79-3 +- make pam_unix LSB 2.0 compliant even when SELinux enabled +- #88127 - change both local and NIS passwords to keep them in sync, + also fix a regression in passwd functionality on NIS master server + +* Tue Apr 5 2005 Tomas Mraz +- #153711 fix wrong logging in pam_selinux when restoring tty label + +* Sun Apr 3 2005 Tomas Mraz 0.79-2 +- fix NULL deref in pam_tally when it's used in account phase + +* Thu Mar 31 2005 Tomas Mraz 0.79-1 +- upgrade to the new upstream release +- moved pam_loginuid to pam-redhat repository + +* Wed Mar 23 2005 Tomas Mraz 0.78-9 +- fix wrong logging in pam_console handlers +- add executing ainit handler for alsa sound dmix +- #147879, #112777 - change permissions for dri devices + +* Fri Mar 18 2005 Tomas Mraz 0.78-8 +- remove ownership and permissions handling from pam_console call + pam_console_apply as a handler instead + +* Mon Mar 14 2005 Tomas Mraz 0.78-7 +- add pam_loginuid module for setting the the login uid for auditing purposes + (by Steve Grubb) + +* Thu Mar 10 2005 Tomas Mraz 0.78-6 +- add functionality for running handler executables from pam_console + when console lock was obtained/lost +- removed patches merged to pam-redhat + +* Tue Mar 1 2005 Tomas Mraz 0.78-5 +- echo why tests failed when rebuilding +- fixed some warnings and errors in pam_console for gcc4 build +- improved parsing pam_console config file + +* Mon Feb 21 2005 Tomas Mraz +- don't log garbage in pam_console_apply (#147879) + +* Tue Jan 18 2005 Tomas Mraz +- don't require exact db4 version only conflict with incompatible one + +* Wed Jan 12 2005 Tomas Mraz 0.78-4 +- updated pam-redhat from elvis CVS +- removed obsolete patches + +* Mon Jan 3 2005 Jeff Johnson 0.78-3 +- depend on db-4.3.27, not db-4.3.21. + +* Thu Nov 25 2004 Tomas Mraz 0.78-2 +- add argument to pam_console_apply to restrict its work to specified files + +* Tue Nov 23 2004 Tomas Mraz 0.78-1 +- update to Linux-PAM-0.78 +- #140451 parse passwd entries correctly and test for failure +- #137802 allow using pam_console for authentication + +* Fri Nov 12 2004 Jeff Johnson 0.77-67 +- rebuild against db-4.3.21. + +* Thu Nov 11 2004 Tomas Mraz 0.77-66 +- #77646 log failures when renaming the files when changing password +- Log failure on missing /etc/security/opasswd when remember option is present + +* Wed Nov 10 2004 Tomas Mraz +- #87628 pam_timestamp remembers authorization after logout +- #116956 fixed memory leaks in pam_stack + +* Wed Oct 20 2004 Tomas Mraz 0.77-65 +- #74062 modify the pwd-lock patch to remove NIS passwd changing deadlock + +* Wed Oct 20 2004 Tomas Mraz 0.77-64 +- #134941 pam_console should check X11 socket only on login + +* Tue Oct 19 2004 Tomas Mraz 0.77-63 +- Fix checking of group %%group syntax in pam_limits +- Drop fencepost patch as it was already fixed + by upstream change from 0.75 to 0.77 +- Fix brokenshadow patch + +* Mon Oct 11 2004 Tomas Mraz 0.77-62 +- Added bluetooth, raw1394 and flash to console.perms +- pam_console manpage fix + +* Mon Oct 11 2004 Tomas Mraz 0.77-61 +- #129328 pam_env shouldn't abort on missing /etc/environment +- #126985 pam_stack should always copy the conversation function +- #127524 add /etc/security/opasswd to files + +* Tue Sep 28 2004 Phil Knirsch 0.77-60 +- Drop last patch again, fixed now correctly elsewhere + +* Thu Sep 23 2004 Phil Knirsch 0.77-59 +- Fixed bug in pam_env where wrong initializer was used + +* Fri Sep 17 2004 Dan Walsh 0.77-58 +- rebuild selinux patch using checkPasswdAccess + +* Mon Sep 13 2004 Jindrich Novy +- rebuilt + +* Mon Sep 13 2004 Tomas Mraz 0.77-56 +- #75454 fixed locking when changing password +- #127054 +- #125653 removed unnecessary getgrouplist call +- #124979 added quiet option to pam_succeed_if + +* Mon Aug 30 2004 Warren Togami 0.77-55 +- #126024 /dev/pmu console perms + +* Wed Aug 4 2004 Dan Walsh 0.77-54 +- Move pam_console.lock to /var/run/console/ + +* Thu Jul 29 2004 Dan Walsh 0.77-53 +- Close fd[1] before pam_modutilread so that unix_verify will complete + +* Tue Jul 27 2004 Alan Cox 0.77-52 +- First chunk of Steve Grubb's resource leak and other fixes + +* Tue Jul 27 2004 Alan Cox 0.77-51 +- Fixed build testing of modules +- Fixed dependancies + +* Tue Jul 20 2004 Dan Walsh 0.77-50 +- Change unix_chkpwd to return pam error codes + +* Sat Jul 10 2004 Alan Cox +- Fixed the pam glib2 dependancy issue + +* Mon Jun 21 2004 Alan Cox +- Fixed the pam_limits fencepost error (#79989) since nobody seems to + be doing it + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Wed Jun 9 2004 Dan Walsh 0.77-45 +- Add requires libselinux > 1.8 + +* Thu Jun 3 2004 Dan Walsh 0.77-44 +- Add MLS Support to selinux patch + +* Wed Jun 2 2004 Dan Walsh 0.77-43 +- Modify pam_selinux to use open and close param + +* Fri May 28 2004 Dan Walsh 0.77-42 +- Split pam module into two parts open and close + +* Tue May 18 2004 Phil Knirsch 0.77-41 +- Fixed 64bit segfault in pam_succeed_if module. + +* Wed Apr 14 2004 Dan Walsh 0.77-40 +- Apply changes from audit. + +* Mon Apr 12 2004 Dan Walsh 0.77-39 +- Change to only report failure on relabel if debug + +* Wed Mar 3 2004 Dan Walsh 0.77-38 +- Fix error handling of pam_unix + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Thu Feb 26 2004 Dan Walsh 0.77-36 +- fix tty handling + +* Thu Feb 26 2004 Dan Walsh 0.77-35 +- remove tty closing and opening from pam_selinux, it does not work. + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Thu Feb 12 2004 Nalin Dahyabhai +- pam_unix: also log successful password changes when using shadowed passwords + +* Tue Feb 10 2004 Dan Walsh 0.77-33 +- close and reopen terminal after changing context. + +* Thu Feb 5 2004 Dan Walsh 0.77-32 +- Check for valid tty + +* Tue Feb 3 2004 Dan Walsh 0.77-31 +- Check for multiple > 1 + +* Mon Feb 2 2004 Dan Walsh 0.77-30 +- fix is_selinux_enabled call for pam_rootok + +* Wed Jan 28 2004 Dan Walsh 0.77-29 +- More fixes to pam_selinux,pam_rootok + +* Wed Jan 28 2004 Dan Walsh 0.77-28 +- turn on selinux + +* Wed Jan 28 2004 Dan Walsh 0.77-27 +- Fix rootok check. + +* Mon Jan 26 2004 Dan Walsh 0.77-26 +- fix is_selinux_enabled call + +* Sun Jan 25 2004 Dan Walsh 0.77-25 +- Check if ROOTOK for SELinux + +* Thu Jan 15 2004 Dan Walsh 0.77-24 +- Fix tty handling for pts in pam_selinux + +* Thu Jan 15 2004 Dan Walsh 0.77-23 +- Need to add qualifier context for sudo situation + +* Thu Jan 15 2004 Dan Walsh 0.77-22 +- Fix pam_selinux to use prevcon instead of pam_user so it will work for su. + +* Fri Dec 12 2003 Bill Nottingham 0.77-21.sel +- add alsa devs to console.perms + +* Thu Dec 11 2003 Jeff Johnson 0.77-20.sel +- rebuild with db-4.2.52. +- build db4 in build_unix, not dist. + +* Wed Nov 26 2003 Dan Walsh 0.77-19.sel +- Change unix_chkpwd to handle unix_passwd and unix_acct +- This eliminates the need for pam modules to have read/write access to /etc/shadow. + +* Thu Nov 20 2003 Dan Walsh 0.77-18.sel +- Cleanup unix_chkpwd + +* Mon Nov 03 2003 Dan Walsh 0.77-17.sel +- Fix tty handling +- Add back multiple handling + +* Mon Oct 27 2003 Dan Walsh 0.77-16.sel +- Remove Multiple from man page of pam_selinux + +* Thu Oct 23 2003 Nalin Dahyabhai 0.77-15 +- don't install _pam_aconf.h -- apps don't use it, other PAM headers which + are installed don't use it, and its contents may be different for arches + on a multilib system +- check for linkage problems in modules at %%install-time (kill #107093 dead) +- add buildprereq on flex (#101563) + +* Wed Oct 22 2003 Nalin Dahyabhai +- make pam_pwdb.so link with libnsl again so that it loads (#107093) +- remove now-bogus buildprereq on db4-devel (we use a bundled copy for + pam_userdb to avoid symbol collisions with other db libraries in apps) + +* Mon Oct 20 2003 Dan Walsh 0.77-14.sel +- Add Russell Coker patch to handle /dev/pty + +* Fri Oct 17 2003 Dan Walsh 0.77-13.sel +- Turn on Selinux + +* Fri Oct 17 2003 Dan Walsh 0.77-12 +- Fix pam_timestamp to work when 0 seconds have elapsed + +* Mon Oct 6 2003 Dan Walsh 0.77-11 +- Turn off selinux + +* Thu Sep 25 2003 Dan Walsh 0.77-10.sel +- Turn on Selinux and remove multiple choice of context. + +* Wed Sep 24 2003 Dan Walsh 0.77-10 +- Turn off selinux + +* Wed Sep 24 2003 Dan Walsh 0.77-9.sel +- Add Russell's patch to check password + +* Wed Sep 17 2003 Dan Walsh 0.77-8.sel +- handle ttys correctly in pam_selinux + +* Fri Sep 05 2003 Dan Walsh 0.77-7.sel +- Clean up memory problems and fix tty handling. + +* Mon Jul 28 2003 Dan Walsh 0.77-6 +- Add manual context selection to pam_selinux + +* Mon Jul 28 2003 Dan Walsh 0.77-5 +- Add pam_selinux + +* Mon Jul 28 2003 Dan Walsh 0.77-4 +- Add SELinux support + +* Thu Jul 24 2003 Nalin Dahyabhai 0.77-3 +- pam_postgresok: add +- pam_xauth: add "targetuser" argument + +* Tue Jul 22 2003 Nalin Dahyabhai +- pam_succeed_if: fix thinko in argument parsing which would walk past the + end of the argument list + +* Wed Jul 9 2003 Nalin Dahyabhai 0.77-2 +- reapply: + - set handler for SIGCHLD to SIG_DFL around *_chkpwd, not SIG_IGN + +* Mon Jul 7 2003 Nalin Dahyabhai 0.77-1 +- pam_timestamp: fail if the key file doesn't contain enough data + +* Thu Jul 3 2003 Nalin Dahyabhai 0.77-0 +- update to 0.77 upstream release + - pam_limits: limits now affect root as well + - pam_nologin: returns PAM_IGNORE instead of PAM_SUCCESS unless "successok" + is given as an argument + - pam_userdb: correctly return PAM_AUTH_ERR instead of PAM_USER_UNKNOWN when + invoked with the "key_only" argument and the database has an entry of the + form "user-" +- use a bundled libdb for pam_userdb.so because the system copy uses threads, + and demand-loading a shared library which uses threads into an application + which doesn't is a Very Bad Idea + +* Thu Jul 3 2003 Nalin Dahyabhai +- pam_timestamp: use a message authentication code to validate timestamp files + +* Mon Jun 30 2003 Nalin Dahyabhai 0.75-48.1 +- rebuild + +* Mon Jun 9 2003 Nalin Dahyabhai 0.75-49 +- modify calls to getlogin() to check the directory of the current TTY before + searching for an entry in the utmp/utmpx file (#98020, #98826, CAN-2003-0388) + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Mon Feb 10 2003 Bill Nottingham 0.75-48 +- set handler for SIGCHLD to SIG_DFL around *_chkpwd, not SIG_IGN + +* Wed Jan 22 2003 Tim Powers 0.75-47 +- rebuilt + +* Tue Dec 17 2002 Nalin Dahyabhai 0.75-46 +- pam_xauth: reintroduce ACL support, per the original white paper +- pam_xauth: default root's export ACL to none instead of everyone + +* Mon Dec 2 2002 Nalin Dahyabhai 0.75-45 +- create /lib/security, even if it isn't /%%{_lib}/security, because we + can't locate /lib/security/$ISA without it (noted by Arnd Bergmann) +- clear out the duplicate docs directory created during %%install + +* Thu Nov 21 2002 Nalin Dahyabhai 0.75-44 +- fix syntax errors in pam_console's yacc parser which newer bison chokes on +- forcibly set FAKEROOT at make install time + +* Tue Oct 22 2002 Nalin Dahyabhai 0.75-43 +- patch to interpret $ISA in case the fist module load attempt fails +- use $ISA in default configs + +* Fri Oct 04 2002 Elliot Lee 0.75-42 +- Since cracklib-dicts location will not be correctly detected without + that package being installed, add buildreq for cracklib-dicts. +- Add patch57: makes configure use $LIBNAME when searching for cracklib + dicts, and error out if not found. + +* Thu Sep 12 2002 Than Ngo 0.75-41.1 +- Fixed pam config files + +* Wed Sep 11 2002 Than Ngo 0.75-41 +- Added fix to install libs in correct directory on 64bit machine + +* Fri Aug 2 2002 Nalin Dahyabhai 0.75-40 +- pam_timestamp_check: check that stdio descriptors are open before we're + invoked +- add missing chroot.conf + +* Mon Jul 29 2002 Nalin Dahyabhai 0.75-39 +- pam_timestamp: sundry fixes, use "unknown" as the tty when none is found + +* Thu Jun 27 2002 Nalin Dahyabhai 0.75-38 +- pam_timestamp_check: be as smart about figuring out the tty as the module is + +* Wed Jun 19 2002 Nalin Dahyabhai 0.75-37 +- pam_timestamp_check: remove extra unlink() call spotted by Havoc + +* Mon Jun 17 2002 Nalin Dahyabhai 0.75-36 +- pam_timestamp: chown intermediate directories when creating them +- pam_timestamp_check: add -d flag to poll + +* Thu May 23 2002 Nalin Dahyabhai 0.75-35 +- pam_timestamp: add some sanity checks +- pam_timestamp_check: add + +* Wed May 22 2002 Nalin Dahyabhai 0.75-34 +- pam_timestamp: add a 'verbose' option + +* Thu May 16 2002 Nalin Dahyabhai 0.75-33 +- rebuild with db4 +- just bundle install-sh into the source package + +* Tue Apr 9 2002 Nalin Dahyabhai 0.75-32 +- pam_unix: be more compatible with AIX-style shadowing (#19236) + +* Thu Mar 28 2002 Nalin Dahyabhai 0.75-31 +- libpam_misc: fix possible infinite loop in misc_conv (#62195) +- pam_xauth: fix cases where DISPLAY is "localhost:screen" and the xauth + key is actually stored using the system's hostname (#61524) + +* Mon Mar 25 2002 Nalin Dahyabhai 0.75-30 +- rebuild + +* Mon Mar 25 2002 Nalin Dahyabhai 0.75-29 +- rebuild + +* Mon Mar 11 2002 Nalin Dahyabhai 0.75-28 +- include the pwdb config file + +* Fri Mar 1 2002 Nalin Dahyabhai 0.75-27 +- adjust the pwdb-static patch to build pam_radius correctly (#59408) + +* Fri Mar 1 2002 Nalin Dahyabhai 0.75-26 +- change the db4-devel build dependency to db3-devel + +* Thu Feb 21 2002 Nalin Dahyabhai 0.75-25 +- rebuild + +* Fri Feb 8 2002 Nalin Dahyabhai 0.75-24 +- pam_unix: log successful password changes +- remove pam_timestamp + +* Thu Feb 7 2002 Nalin Dahyabhai 0.75-23 +- fix pwdb embedding +- add pam_timestamp + +* Thu Jan 31 2002 Nalin Dahyabhai 0.75-22 +- swallow up pwdb 0.61.1 for building pam_pwdb + +* Wed Jan 23 2002 Nalin Dahyabhai 0.75-21 +- pam_userdb: build with db4 instead of db3 + +* Thu Nov 22 2001 Nalin Dahyabhai 0.75-20 +- pam_stack: fix some memory leaks (reported by Fernando Trias) +- pam_chroot: integrate Owl patch to report the more common causes of failures + +* Fri Nov 9 2001 Nalin Dahyabhai 0.75-19 +- fix a bug in the getpwnam_r wrapper which sometimes resulted in false + positives for non-existent users + +* Wed Nov 7 2001 Nalin Dahyabhai 0.75-18 +- include libpamc in the pam package (#55651) + +* Fri Nov 2 2001 Nalin Dahyabhai 0.75-17 +- pam_xauth: don't free a string after passing it to putenv() + +* Wed Oct 24 2001 Nalin Dahyabhai 0.75-16 +- pam_xauth: always return PAM_SUCCESS or PAM_SESSION_ERR instead of PAM_IGNORE, + matching the previous behavior (libpam treats PAM_IGNORE from a single module + in a stack as a session error, leading to false error messages if we just + return PAM_IGNORE for all cases) + +* Mon Oct 22 2001 Nalin Dahyabhai 0.75-15 +- reorder patches so that the reentrancy patch is applied last -- we never + came to a consensus on how to guard against the bugs in calling applications + which this sort of change addresses, and having them last allows for dropping + in a better strategy for addressing this later on + +* Mon Oct 15 2001 Nalin Dahyabhai +- pam_rhosts: allow "+hostname" as a synonym for "hostname" to jive better + with the hosts.equiv(5) man page +- use the automake install-sh instead of the autoconf install-sh, which + disappeared somewhere between 2.50 and now + +* Mon Oct 8 2001 Nalin Dahyabhai +- add pwdb as a buildprereq + +* Fri Oct 5 2001 Nalin Dahyabhai +- pam_tally: don't try to read past the end of faillog -- it probably contains + garbage, which if written into the file later on will confuse /usr/bin/faillog + +* Thu Oct 4 2001 Nalin Dahyabhai +- pam_limits: don't just return if the user is root -- we'll want to set the + priority (it could be negative to elevate root's sessions) +- pam_issue: fix off-by-one error allocating space for the prompt string + +* Wed Oct 3 2001 Nalin Dahyabhai +- pam_mkhomedir: recurse into subdirectories properly +- pam_mkhomedir: handle symlinks +- pam_mkhomedir: skip over special items in the skeleton directory + +* Tue Oct 2 2001 Nalin Dahyabhai +- add cracklib as a buildprereq +- pam_wheel: don't ignore out if the user is attempting to switch to a + unprivileged user (this lets pam_wheel do its thing when users attempt + to get to system accounts or accounts of other unprivileged users) + +* Fri Sep 28 2001 Nalin Dahyabhai +- pam_xauth: close a possible DoS due to use of dotlock-style locking in + world-writable directories by relocating the temporary file to the target + user's home directory +- general: include headers local to this tree using relative paths so that + system headers for PAM won't be pulled in, in case include paths don't + take care of it + +* Thu Sep 27 2001 Nalin Dahyabhai +- pam_xauth: rewrite to skip refcounting and just use a temporary file + created using mkstemp() in /tmp + +* Tue Sep 25 2001 Nalin Dahyabhai +- pam_userdb: fix the key_only flag so that the null-terminator of the + user-password string isn't expected to be part of the key in the db file, + matching the behavior of db_load 3.2.9 + +* Mon Sep 24 2001 Nalin Dahyabhai +- pam_unix: use crypt() instead of bigcrypt() when salted field is less than + the critical size which lets us know it was generated with bigcrypt() +- use a wrapper to handle ERANGE errors when calling get....._r functions: + defining PAM_GETPWNAM_R and such (for getpwnam, getpwuid, getgrnam, + getgrgid, and getspnam) before including _pam_macros.h will cause them + to be implemented as static functions, similar to how defining PAM_SM_xxx + is used to control whether or not PAM declares prototypes for certain + functions + +* Mon Sep 24 2001 Nalin Dahyabhai 0.75-14 +- pam_unix: argh, compare entire pruned salt string with crypted result, always + +* Sat Sep 8 2001 Bill Nottingham 0.75-13 +- ship /lib/lib{pam,pam_misc}.so for legacy package builds + +* Thu Sep 6 2001 Nalin Dahyabhai 0.75-12 +- noreplace configuration files in /etc/security +- pam_console: update pam_console_apply and man pages to reflect + /var/lock -> /var/run move + +* Wed Sep 5 2001 Nalin Dahyabhai 0.75-11 +- pam_unix: fix the fix for #42394 + +* Tue Sep 4 2001 Nalin Dahyabhai +- modules: use getpwnam_r and friends instead of non-reentrant versions +- pam_console: clear generated .c and .h files in "clean" makefile target + +* Thu Aug 30 2001 Nalin Dahyabhai +- pam_stack: perform deep copy of conversation structures +- include the static libpam in the -devel subpackage (#52321) +- move development .so and .a files to %%{_libdir} +- pam_unix: don't barf on empty passwords (#51846) +- pam_unix: redo compatibility with "hash,age" data wrt bigcrypt (#42394) +- console.perms: add usb camera, scanner, and rio devices (#15528) +- pam_cracklib: initialize all options properly (#49613) + +* Wed Aug 22 2001 Nalin Dahyabhai +- pam_limits: don't rule out negative priorities + +* Mon Aug 13 2001 Nalin Dahyabhai 0.75-10 +- pam_xauth: fix errors due to uninitialized data structure (fix from Tse Huong + Choo) +- pam_xauth: random cleanups +- pam_console: use /var/run/console instead of /var/lock/console at install-time +- pam_unix: fix preserving of permissions on files which are manipulated + +* Fri Aug 10 2001 Bill Nottingham +- fix segfault in pam_securetty + +* Thu Aug 9 2001 Nalin Dahyabhai +- pam_console: use /var/run/console instead of /var/lock/console for lock files +- pam_issue: read the right number of bytes from the file + +* Mon Jul 9 2001 Nalin Dahyabhai +- pam_wheel: don't error out if the group has no members, but is the user's + primary GID (reported by David Vos) +- pam_unix: preserve permissions on files which are manipulated (#43706) +- pam_securetty: check if the user is the superuser before checking the tty, + thereby allowing regular users access to services which don't set the + PAM_TTY item (#39247) +- pam_access: define NIS and link with libnsl (#36864) + +* Thu Jul 5 2001 Nalin Dahyabhai +- link libpam_misc against libpam + +* Tue Jul 3 2001 Nalin Dahyabhai +- pam_chroot: chdir() before chroot() + +* Fri Jun 29 2001 Nalin Dahyabhai +- pam_console: fix logic bug when changing permissions on single + file and/or lists of files +- pam_console: return the proper error code (reported and patches + for both from Frederic Crozat) +- change deprecated Copyright: tag in .spec file to License: + +* Mon Jun 25 2001 Nalin Dahyabhai +- console.perms: change js* to js[0-9]* +- include pam_aconf.h in more modules (patches from Harald Welte) + +* Thu May 24 2001 Nalin Dahyabhai +- console.perms: add apm_bios to the list of devices the console owner can use +- console.perms: add beep to the list of sound devices + +* Mon May 7 2001 Nalin Dahyabhai +- link pam_console_apply statically with libglib (#38891) + +* Mon Apr 30 2001 Nalin Dahyabhai +- pam_access: compare IP addresses with the terminating ".", as documented + (patch from Carlo Marcelo Arenas Belon, I think) (#16505) + +* Mon Apr 23 2001 Nalin Dahyabhai +- merge up to 0.75 +- pam_unix: temporarily ignore SIGCHLD while running the helper +- pam_pwdb: temporarily ignore SIGCHLD while running the helper +- pam_dispatch: default to uncached behavior if the cached chain is empty + +* Fri Apr 6 2001 Nalin Dahyabhai +- correct speling errors in various debug messages and doc files (#33494) + +* Thu Apr 5 2001 Nalin Dahyabhai +- prereq sed, fileutils (used in %%post) + +* Wed Apr 4 2001 Nalin Dahyabhai +- remove /dev/dri from console.perms -- XFree86 munges it, so it's outside of + our control (reminder from Daryll Strauss) +- add /dev/3dfx to console.perms + +* Fri Mar 23 2001 Nalin Dahyabhai +- pam_wheel: make 'trust' and 'deny' work together correctly +- pam_wheel: also check the user's primary gid +- pam_group: also initialize groups when called with PAM_REINITIALIZE_CRED + +* Tue Mar 20 2001 Nalin Dahyabhai +- mention pam_console_apply in the see also section of the pam_console man pages + +* Fri Mar 16 2001 Nalin Dahyabhai +- console.perms: /dev/vc/* should be a regexp, not a glob (thanks to + Charles Lopes) + +* Mon Mar 12 2001 Nalin Dahyabhai +- console.perms: /dev/cdroms/* should belong to the user, from Douglas + Gilbert via Tim Waugh + +* Thu Mar 8 2001 Nalin Dahyabhai +- pam_console_apply: muck with devices even if the mount point doesn't exist + +* Wed Mar 7 2001 Nalin Dahyabhai +- pam_console: error out on undefined classes in pam_console config file +- console.perms: actually change the permissions on the new device classes +- pam_console: add an fstab= argument, and -f and -c flags to pam_console_apply +- pam_console: use g_log instead of g_critical when bailing out +- console.perms: logins on /dev/vc/* are also console logins, from Douglas + Gilbert via Tim Waugh + +* Tue Mar 6 2001 Nalin Dahyabhai +- add pam_console_apply +- /dev/pilot's usually a serial port (or a USB serial port), so revert its + group to 'uucp' instead of 'tty' in console.perms +- change pam_console's behavior wrt directories -- directories which are + mount points according to /etc/fstab are taken to be synonymous with + their device special nodes, and directories which are not mount points + are ignored + +* Tue Feb 27 2001 Nalin Dahyabhai +- handle errors fork()ing in pam_xauth +- make the "other" config noreplace + +* Mon Feb 26 2001 Nalin Dahyabhai +- user should own the /dev/video directory, not the non-existent /dev/v4l +- tweak pam_limits doc + +* Wed Feb 21 2001 Nalin Dahyabhai +- own /etc/security +- be more descriptive when logging messages from pam_limits +- pam_listfile: remove some debugging code (#28346) + +* Mon Feb 19 2001 Nalin Dahyabhai +- pam_lastlog: don't pass NULL to logwtmp() + +* Fri Feb 16 2001 Nalin Dahyabhai +- pam_listfile: fix argument parser (#27773) +- pam_lastlog: link to libutil + +* Tue Feb 13 2001 Nalin Dahyabhai +- pam_limits: change the documented default config file to reflect the defaults +- pam_limits: you should be able to log in a total of maxlogins times, not + (maxlogins - 1) +- handle group limits on maxlogins correctly (#25690) + +* Mon Feb 12 2001 Nalin Dahyabhai +- change the pam_xauth default maximum "system user" ID from 499 to 99 (#26343) + +* Wed Feb 7 2001 Nalin Dahyabhai +- refresh the default system-auth file, pam_access is out + +* Mon Feb 5 2001 Nalin Dahyabhai +- actually time out when attempting to lckpwdf() (#25889) +- include time.h in pam_issue (#25923) +- update the default system-auth to the one generated by authconfig 4.1.1 +- handle getpw??? and getgr??? failures more gracefully (#26115) +- get rid of some extraneous {set,end}{pw,gr}ent() calls + +* Tue Jan 30 2001 Nalin Dahyabhai +- overhaul pam_stack to account for abstraction libpam now provides + +* Tue Jan 23 2001 Nalin Dahyabhai +- remove pam_radius at request of author + +* Mon Jan 22 2001 Nalin Dahyabhai +- merge to 0.74 +- make console.perms match perms set by MAKEDEV, and add some devfs device names +- add 'sed' to the buildprereq list (#24666) + +* Sun Jan 21 2001 Matt Wilson +- added "exit 0" to the end of the pre script + +* Fri Jan 19 2001 Nalin Dahyabhai +- self-hosting fix from Guy Streeter + +* Wed Jan 17 2001 Nalin Dahyabhai +- use gcc for LD_L to pull in intrinsic stuff on ia64 + +* Fri Jan 12 2001 Nalin Dahyabhai +- take another whack at compatibility with "hash,age" data in pam_unix (#21603) + +* Wed Jan 10 2001 Nalin Dahyabhai +- make the -devel subpackage unconditional + +* Tue Jan 9 2001 Nalin Dahyabhai +- merge/update to 0.73 + +* Mon Dec 18 2000 Nalin Dahyabhai +- refresh from CVS -- some weird stuff crept into pam_unix + +* Tue Dec 12 2000 Nalin Dahyabhai +- fix handling of "nis" when changing passwords by adding the checks for the + data source to the password-updating module in pam_unix +- add the original copyright for pam_access (fix from Michael Gerdts) + +* Thu Nov 30 2000 Nalin Dahyabhai +- redo similar() using a distance algorithm and drop the default dif_ok to 5 +- readd -devel + +* Wed Nov 29 2000 Nalin Dahyabhai +- fix similar() function in pam_cracklib (#14740) +- fix example in access.conf (#21467) +- add conditional compilation for building for 6.2 (for pam_userdb) +- tweak post to not use USESHADOW any more + +* Tue Nov 28 2000 Nalin Dahyabhai +- make EINVAL setting lock limits in pam_limits non-fatal, because it's a 2.4ism + +* Tue Nov 21 2000 Nalin Dahyabhai +- revert to DB 3.1, which is what we were supposed to be using from the get-go + +* Mon Nov 20 2000 Nalin Dahyabhai +- add RLIMIT_LOCKS to pam_limits (patch from Jes Sorensen) (#20542) +- link pam_userdb to Berkeley DB 2.x to match 6.2's setup correctly + +* Mon Nov 6 2000 Matt Wilson +- remove prereq on sh-utils, test ([) is built in to bash + +* Thu Oct 19 2000 Nalin Dahyabhai +- fix the pam_userdb module breaking + +* Wed Oct 18 2000 Nalin Dahyabhai +- fix pam_unix likeauth argument for authenticate(),setcred(),setcred() + +* Tue Oct 17 2000 Nalin Dahyabhai +- tweak pre script to be called in all upgrade cases +- get pam_unix to only care about the significant pieces of passwords it checks +- add /usr/include/db1/db.h as a build prereq to pull in the right include + files, no matter whether they're in glibc-devel or db1-devel +- pam_userdb.c: include db1/db.h instead of db.h + +* Wed Oct 11 2000 Nalin Dahyabhai +- add BuildPrereq for bison (suggested by Bryan Stillwell) + +* Fri Oct 6 2000 Nalin Dahyabhai +- patch from Dmitry V. Levin to have pam_stack propagate the PAM fail_delay +- roll back the README for pam_xauth to actually be the right one +- tweak pam_stack to use the parent's service name when calling the substack + +* Wed Oct 4 2000 Nalin Dahyabhai +- create /etc/sysconfig/authconfig at install-time if upgrading + +* Mon Oct 2 2000 Nalin Dahyabhai +- modify the files list to make sure #16456 stays fixed +- make pam_stack track PAM_AUTHTOK and PAM_OLDAUTHTOK items +- add pam_chroot module +- self-hosting fixes from the -devel split +- update generated docs in the tree + +* Tue Sep 12 2000 Nalin Dahyabhai +- split off a -devel subpackage +- install the developer man pages + +* Sun Sep 10 2000 Bill Nottingham +- build libraries before modules + +* Wed Sep 6 2000 Nalin Dahyabhai +- fix problems when looking for headers in /usr/include (#17236) +- clean up a couple of compile warnings + +* Tue Aug 22 2000 Nalin Dahyabhai +- give users /dev/cdrom* instead of /dev/cdrom in console.perms (#16768) +- add nvidia control files to console.perms + +* Tue Aug 22 2000 Bill Nottingham +- add DRI devices to console.perms (#16731) + +* Thu Aug 17 2000 Nalin Dahyabhai +- move pam_filter modules to /lib/security/pam_filter (#16111) +- add pam_tally's application to allow counts to be reset (#16456) +- move README files to the txts subdirectory + +* Mon Aug 14 2000 Nalin Dahyabhai +- add a postun that runs ldconfig +- clean up logging in pam_xauth + +* Fri Aug 4 2000 Nalin Dahyabhai +- make the tarball include the release number in its name + +* Mon Jul 31 2000 Nalin Dahyabhai +- add a broken_shadow option to pam_unix +- add all module README files to the documentation list (#16456) + +* Tue Jul 25 2000 Nalin Dahyabhai +- fix pam_stack debug and losing-track-of-the-result bug + +* Mon Jul 24 2000 Nalin Dahyabhai +- rework pam_console's usage of syslog to actually be sane (#14646) + +* Sat Jul 22 2000 Nalin Dahyabhai +- take the LOG_ERR flag off of some of pam_console's new messages + +* Fri Jul 21 2000 Nalin Dahyabhai +- add pam_localuser + +* Wed Jul 12 2000 Nalin Dahyabhai +- need to make pam_console's checking a little stronger +- only pass data up from pam_stack if the parent didn't already define it + +* Wed Jul 12 2000 Prospector +- automatic rebuild + +* Tue Jul 11 2000 Nalin Dahyabhai +- make pam_console's extra checks disableable +- simplify extra check to just check if the device owner is root +- add a debug log when pam_stack comes across a NULL item +- have pam_stack hand items up to the parent from the child + +* Mon Jul 3 2000 Nalin Dahyabhai +- fix installation of pam_xauth man pages (#12417) +- forcibly strip helpers (#12430) +- try to make pam_console a little more discriminating + +* Mon Jun 19 2000 Nalin Dahyabhai +- symlink libpam.so to libpam.so.%%{version}, and likewise for libpam_misc +- reverse order of checks in _unix_getpwnam for pam_unix + +* Wed Jun 14 2000 Preston Brown +- include gpmctl in pam_console + +* Mon Jun 05 2000 Nalin Dahyabhai +- add MANDIR definition and use it when installing man pages + +* Mon Jun 05 2000 Preston Brown +- handle scanner and cdwriter devices in pam_console + +* Sat Jun 3 2000 Nalin Dahyabhai +- add account management wrappers for pam_listfile, pam_nologin, pam_securetty, + pam_shells, and pam_wheel + +* Thu Jun 1 2000 Nalin Dahyabhai +- add system-auth control file +- let gethostname() call in pam_access.c be implicitly declared to avoid + conflicting types if unistd.c declares it + +* Mon May 15 2000 Nalin Dahyabhai +- fix problems compiling on Red Hat Linux 5.x (bug #11005) + +* Wed Apr 26 2000 Bill Nottingham +- fix size assumptions in pam_(pwdb|unix) md5 code + +* Mon Mar 20 2000 Nalin Dahyabhai +- Add new pam_stack module. +- Install pwdb_chkpwd and unix_chkpwd as the current user for non-root builds + +* Sat Feb 05 2000 Nalin Dahyabhai +- Fix pam_xauth bug #6191. + +* Thu Feb 03 2000 Elliot Lee +- Add a patch to accept 'pts/N' in /etc/securetty as a match for tty '5' + (which is what other pieces of the system think it is). Fixes bug #7641. + +* Mon Jan 31 2000 Nalin Dahyabhai +- argh, turn off gratuitous debugging + +* Wed Jan 19 2000 Nalin Dahyabhai +- update to 0.72 +- fix pam_unix password-changing bug +- fix pam_unix's cracklib support +- change package URL + +* Mon Jan 03 2000 Cristian Gafton +- don't allow '/' on service_name + +* Thu Oct 21 1999 Cristian Gafton +- enhance the pam_userdb module some more + +* Fri Sep 24 1999 Cristian Gafton +- add documenatation + +* Tue Sep 21 1999 Michael K. Johnson +- a tiny change to pam_console to make it not loose track of console users + +* Mon Sep 20 1999 Michael K. Johnson +- a few fixes to pam_xauth to make it more robust + +* Wed Jul 14 1999 Michael K. Johnson +- pam_console: added to manage /dev/console + +* Thu Jul 01 1999 Michael K. Johnson +- pam_xauth: New refcounting implementation based on idea from Stephen Tweedie + +* Sat Apr 17 1999 Michael K. Johnson +- added video4linux devices to /etc/security/console.perms + +* Fri Apr 16 1999 Michael K. Johnson +- added joystick lines to /etc/security/console.perms + +* Thu Apr 15 1999 Michael K. Johnson +- fixed a couple segfaults in pam_xauth uncovered by yesterday's fix... + +* Wed Apr 14 1999 Cristian Gafton +- use gcc -shared to link the shared libs + +* Wed Apr 14 1999 Michael K. Johnson +- many bug fixes in pam_xauth +- pam_console can now handle broken applications that do not set + the PAM_TTY item. + +* Tue Apr 13 1999 Michael K. Johnson +- fixed glob/regexp confusion in pam_console, added kbd and fixed fb devices +- added pam_xauth module + +* Sat Apr 10 1999 Cristian Gafton +- pam_lastlog does wtmp handling now + +* Thu Apr 08 1999 Michael K. Johnson +- added option parsing to pam_console +- added framebuffer devices to default console.perms settings + +* Wed Apr 07 1999 Cristian Gafton +- fixed empty passwd handling in pam_pwdb + +* Mon Mar 29 1999 Michael K. Johnson +- changed /dev/cdrom default user permissions back to 0600 in console.perms + because some cdrom players open O_RDWR. + +* Fri Mar 26 1999 Michael K. Johnson +- added /dev/jaz and /dev/zip to console.perms + +* Thu Mar 25 1999 Michael K. Johnson +- changed the default user permissions for /dev/cdrom to 0400 in console.perms + +* Fri Mar 19 1999 Michael K. Johnson +- fixed a few bugs in pam_console + +* Thu Mar 18 1999 Michael K. Johnson +- pam_console authentication working +- added /etc/security/console.apps directory + +* Mon Mar 15 1999 Michael K. Johnson +- added pam_console files to filelist + +* Fri Feb 12 1999 Cristian Gafton +- upgraded to 0.66, some source cleanups + +* Mon Dec 28 1998 Cristian Gafton +- add patch from Savochkin Andrey Vladimirovich for umask + security risk + +* Fri Dec 18 1998 Cristian Gafton +- upgrade to ver 0.65 +- build the package out of internal CVS server