diff --git a/.gitignore b/.gitignore index 83e1e1a..26bd019 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/shadow-4.1.5.1.tar.bz2 +SOURCES/shadow-4.6.tar.xz diff --git a/.shadow-utils.metadata b/.shadow-utils.metadata index a736791..65c37db 100644 --- a/.shadow-utils.metadata +++ b/.shadow-utils.metadata @@ -1 +1 @@ -81f38720b953ef9c2c100c43d02dfe19cafd6c30 SOURCES/shadow-4.1.5.1.tar.bz2 +0b84eb1010fda5edca2a9d1733f9480200e02de6 SOURCES/shadow-4.6.tar.xz 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/shadow-4.1.5-2ndskip.patch b/SOURCES/shadow-4.1.5-2ndskip.patch deleted file mode 100644 index 8a9cf68..0000000 --- a/SOURCES/shadow-4.1.5-2ndskip.patch +++ /dev/null @@ -1,100 +0,0 @@ -diff -up shadow-4.1.5/src/grpconv.c.2ndskip shadow-4.1.5/src/grpconv.c ---- shadow-4.1.5/src/grpconv.c.2ndskip 2012-06-18 13:08:34.438910815 +0200 -+++ shadow-4.1.5/src/grpconv.c 2012-06-18 13:12:51.270764552 +0200 -@@ -143,6 +143,7 @@ int main (int argc, char **argv) - struct group grent; - const struct sgrp *sg; - struct sgrp sgent; -+ char *np; - - Prog = Basename (argv[0]); - -@@ -184,20 +185,25 @@ int main (int argc, char **argv) - * Remove /etc/gshadow entries for groups not in /etc/group. - */ - (void) sgr_rewind (); -- while ((sg = sgr_next ()) != NULL) { -- if (gr_locate (sg->sg_name) != NULL) { -- continue; -- } -- -- if (sgr_remove (sg->sg_name) == 0) { -- /* -- * This shouldn't happen (the entry exists) but... -- */ -- fprintf (stderr, -- _("%s: cannot remove entry '%s' from %s\n"), -- Prog, sg->sg_name, sgr_dbname ()); -- fail_exit (3); -+ sg = sgr_next (); -+ np=NULL; -+ while (sg != NULL) { -+ np = strdup(sg->sg_name); -+ sg = sgr_next (); -+ -+ if(gr_locate (np) == NULL) { -+ if (sgr_remove (np) == 0) { -+ /* -+ * This shouldn't happen (the entry exists) but... -+ */ -+ fprintf (stderr, -+ _("%s: cannot remove entry '%s' from %s\n"), -+ Prog, np, sgr_dbname ()); -+ free(np); -+ fail_exit (3); -+ } - } -+ free(np); - } - - /* -diff -up shadow-4.1.5/src/pwconv.c.2ndskip shadow-4.1.5/src/pwconv.c ---- shadow-4.1.5/src/pwconv.c.2ndskip 2012-06-18 11:23:33.938511797 +0200 -+++ shadow-4.1.5/src/pwconv.c 2012-06-18 12:57:18.396426194 +0200 -@@ -173,6 +173,7 @@ int main (int argc, char **argv) - struct passwd pwent; - const struct spwd *sp; - struct spwd spent; -+ char *np; - - Prog = Basename (argv[0]); - -@@ -223,20 +224,25 @@ int main (int argc, char **argv) - * Remove /etc/shadow entries for users not in /etc/passwd. - */ - (void) spw_rewind (); -- while ((sp = spw_next ()) != NULL) { -- if (pw_locate (sp->sp_namp) != NULL) { -- continue; -- } -- -- if (spw_remove (sp->sp_namp) == 0) { -- /* -- * This shouldn't happen (the entry exists) but... -- */ -- fprintf (stderr, -- _("%s: cannot remove entry '%s' from %s\n"), -- Prog, sp->sp_namp, spw_dbname ()); -- fail_exit (E_FAILURE); -+ sp = spw_next (); -+ np = NULL; -+ while (sp != NULL) { -+ np = strdup(sp->sp_namp); -+ sp = spw_next (); -+ -+ if (pw_locate (np) == NULL) { -+ if (spw_remove (np) == 0) { -+ /* -+ * This shouldn't happen (the entry exists) but... -+ */ -+ fprintf (stderr, -+ _("%s: cannot remove entry '%s' from %s\n"), -+ Prog, np, spw_dbname ()); -+ free(np); -+ fail_exit (E_FAILURE); -+ } - } -+ free(np); - } - - /* diff --git a/SOURCES/shadow-4.1.5-redhat.patch b/SOURCES/shadow-4.1.5-redhat.patch deleted file mode 100644 index a785b29..0000000 --- a/SOURCES/shadow-4.1.5-redhat.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -up shadow-4.1.5/man/useradd.8.redhat shadow-4.1.5/man/useradd.8 -diff -up shadow-4.1.5/src/useradd.c.redhat shadow-4.1.5/src/useradd.c ---- shadow-4.1.5/src/useradd.c.redhat 2011-12-09 23:23:15.000000000 +0100 -+++ shadow-4.1.5/src/useradd.c 2012-03-19 09:50:05.227588669 +0100 -@@ -93,7 +93,7 @@ const char *Prog; - static gid_t def_group = 100; - static const char *def_gname = "other"; - static const char *def_home = "/home"; --static const char *def_shell = ""; -+static const char *def_shell = "/sbin/nologin"; - static const char *def_template = SKEL_DIR; - static const char *def_create_mail_spool = "no"; - -@@ -103,7 +103,7 @@ static const char *def_expire = ""; - #define VALID(s) (strcspn (s, ":\n") == strlen (s)) - - static const char *user_name = ""; --static const char *user_pass = "!"; -+static const char *user_pass = "!!"; - static uid_t user_id; - static gid_t user_gid; - static const char *user_comment = ""; -@@ -1011,9 +1011,9 @@ static void process_flags (int argc, cha - }; - while ((c = getopt_long (argc, argv, - #ifdef WITH_SELINUX -- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:s:u:UZ:", -+ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:s:u:UZ:", - #else /* !WITH_SELINUX */ -- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:s:u:U", -+ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:s:u:U", - #endif /* !WITH_SELINUX */ - long_options, NULL)) != -1) { - switch (c) { -@@ -1164,6 +1164,7 @@ static void process_flags (int argc, cha - case 'M': - Mflg = true; - break; -+ case 'n': - case 'N': - Nflg = true; - break; diff --git a/SOURCES/shadow-4.1.5-uflg.patch b/SOURCES/shadow-4.1.5-uflg.patch deleted file mode 100644 index f72bca3..0000000 --- a/SOURCES/shadow-4.1.5-uflg.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -up shadow-4.1.5/libmisc/find_new_gid.c.uflg shadow-4.1.5/libmisc/find_new_gid.c ---- shadow-4.1.5/libmisc/find_new_gid.c.uflg 2011-07-30 01:10:27.000000000 +0200 -+++ shadow-4.1.5/libmisc/find_new_gid.c 2012-03-19 12:51:46.090554116 +0100 -@@ -68,7 +68,7 @@ int find_new_gid (bool sys_group, - return -1; - } - } else { -- gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); -+ gid_min = (gid_t) 1; - gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1; - gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max); - if (gid_max < gid_min) { -@@ -100,6 +100,10 @@ int find_new_gid (bool sys_group, - return 0; - } - -+ /* if we did not find free preffered system gid, we start to look for -+ * one in the range assigned to dynamic system IDs */ -+ if (sys_group) -+ gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); - - /* - * Search the entire group file, diff --git a/SOURCES/shadow-4.1.5.1-audit-owner.patch b/SOURCES/shadow-4.1.5.1-audit-owner.patch deleted file mode 100644 index 6fbbdbf..0000000 --- a/SOURCES/shadow-4.1.5.1-audit-owner.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff -up shadow-4.1.5.1/src/usermod.c.audit shadow-4.1.5.1/src/usermod.c ---- shadow-4.1.5.1/src/usermod.c.audit 2011-11-21 23:02:16.000000000 +0100 -+++ shadow-4.1.5.1/src/usermod.c 2013-06-14 14:54:20.237026550 +0200 -@@ -1513,6 +1513,14 @@ static void move_home (void) - fail_exit (E_HOMEDIR); - } - -+#ifdef WITH_AUDIT -+ if (uflg || gflg) { -+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -+ "changing home directory owner", -+ user_newname, (unsigned int) user_newid, 1); -+ } -+#endif -+ - if (rename (user_home, user_newhome) == 0) { - /* FIXME: rename above may have broken symlinks - * pointing to the user's home directory -@@ -1947,6 +1955,13 @@ int main (int argc, char **argv) - * ownership. - * - */ -+#ifdef WITH_AUDIT -+ if (uflg || gflg) { -+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -+ "changing home directory owner", -+ user_newname, (unsigned int) user_newid, 1); -+ } -+#endif - if (chown_tree (dflg ? user_newhome : user_home, - user_id, - uflg ? user_newid : (uid_t)-1, diff --git a/SOURCES/shadow-4.1.5.1-audit-update.patch b/SOURCES/shadow-4.1.5.1-audit-update.patch deleted file mode 100644 index 17930bf..0000000 --- a/SOURCES/shadow-4.1.5.1-audit-update.patch +++ /dev/null @@ -1,2250 +0,0 @@ -diff -urp shadow-4.1.5.1.orig/lib/prototypes.h shadow-4.1.5.1/lib/prototypes.h ---- shadow-4.1.5.1.orig/lib/prototypes.h 2014-09-13 15:45:54.953829562 -0400 -+++ shadow-4.1.5.1/lib/prototypes.h 2014-10-14 08:39:23.785884075 -0400 -@@ -195,12 +195,21 @@ extern int audit_fd; - extern void audit_help_open (void); - /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ - #define AUDIT_NO_ID ((unsigned int) -1) -+#ifndef AUDIT_GRP_MGMT -+#define AUDIT_GRP_MGMT 1132 /* Group account was modified */ -+#endif -+#ifndef AUDIT_GRP_CHAUTHTOK -+#define AUDIT_GRP_CHAUTHTOK 1133 /* Group account password was changed */ -+#endif - typedef enum { - SHADOW_AUDIT_FAILURE = 0, - SHADOW_AUDIT_SUCCESS = 1} shadow_audit_result; - extern void audit_logger (int type, const char *pgname, const char *op, - const char *name, unsigned int id, - shadow_audit_result result); -+void audit_logger_with_group (int type, unused const char *pgname, -+ const char *op, const char *name, unsigned int id, -+ const char *grp, shadow_audit_result result); - void audit_logger_message (const char *message, shadow_audit_result result); - #endif - -diff -urp shadow-4.1.5.1.orig/libmisc/audit_help.c shadow-4.1.5.1/libmisc/audit_help.c ---- shadow-4.1.5.1.orig/libmisc/audit_help.c 2010-08-21 07:41:28.000000000 -0400 -+++ shadow-4.1.5.1/libmisc/audit_help.c 2014-10-14 08:39:23.785884075 -0400 -@@ -68,7 +68,7 @@ void audit_help_open (void) - * This function will log a message to the audit system using a predefined - * message format. Parameter usage is as follows: - * -- * type - type of message: AUDIT_USER_CHAUTHTOK for changing any account -+ * type - type of message: AUDIT_USER_MGMT for changing any account - * attributes. - * pgname - program's name - * op - operation. "adding user", "changing finger info", "deleting group" -@@ -88,6 +88,39 @@ void audit_logger (int type, unused cons - } - } - -+/* -+ * This function will log a message to the audit system using a predefined -+ * message format. Parameter usage is as follows: -+ * -+ * type - type of message: AUDIT_USER_MGMT for changing any account -+ * attributes. -+ * pgname - program's name -+ * op - operation. "adding user", "changing finger info", "deleting group" -+ * name - user's account or group name. If not available use NULL. -+ * id - uid or gid that the operation is being performed on. This is used -+ * only when user is NULL. -+ * grp - group name associated with event -+ */ -+void audit_logger_with_group (int type, unused const char *pgname, -+ const char *op, const char *name, unsigned int id, -+ const char *grp, shadow_audit_result result) -+{ -+ int len; -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1], buf[1024]; -+ if (audit_fd < 0) { -+ return; -+ } -+ len = strnlen(grp, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(grp, len)) { -+ snprintf(buf, sizeof(buf), "%s grp=%s", op, -+ audit_encode_value(enc_group, grp, len)); -+ } else { -+ snprintf(buf, sizeof(buf), "%s grp=\"%s\"", op, grp); -+ } -+ audit_log_acct_message (audit_fd, type, NULL, buf, name, id, -+ NULL, NULL, NULL, (int) result); -+} -+ - void audit_logger_message (const char *message, shadow_audit_result result) - { - if (audit_fd < 0) { -diff -urp shadow-4.1.5.1.orig/libmisc/cleanup_group.c shadow-4.1.5.1/libmisc/cleanup_group.c ---- shadow-4.1.5.1.orig/libmisc/cleanup_group.c 2008-12-23 17:45:18.000000000 -0500 -+++ shadow-4.1.5.1/libmisc/cleanup_group.c 2014-10-14 09:00:33.594753105 -0400 -@@ -83,7 +83,7 @@ void cleanup_report_mod_group (void *cle - gr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -101,7 +101,7 @@ void cleanup_report_mod_gshadow (void *c - sgr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -122,7 +122,7 @@ void cleanup_report_add_group_group (voi - SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group to /etc/group", -+ "adding-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -141,8 +141,8 @@ void cleanup_report_add_group_gshadow (v - - SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group to /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "adding-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -164,8 +164,8 @@ void cleanup_report_del_group_group (voi - "failed to remove group %s from %s", - name, gr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "removing group from /etc/group", -+ audit_logger (AUDIT_DEL_GROUP, Prog, -+ "removing-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -187,8 +187,8 @@ void cleanup_report_del_group_gshadow (v - "failed to remove group %s from %s", - name, sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "removing group from /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "removing-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -208,7 +208,7 @@ void cleanup_unlock_group (unused void * - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking group file", -+ audit_logger_message ("unlocking-group", - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -228,7 +228,7 @@ void cleanup_unlock_gshadow (unused void - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking gshadow file", -+ audit_logger_message ("unlocking-gshadow", - SHADOW_AUDIT_FAILURE); - #endif - } -diff -urp shadow-4.1.5.1.orig/libmisc/cleanup_user.c shadow-4.1.5.1/libmisc/cleanup_user.c ---- shadow-4.1.5.1.orig/libmisc/cleanup_user.c 2008-12-23 17:45:18.000000000 -0500 -+++ shadow-4.1.5.1/libmisc/cleanup_user.c 2014-10-14 09:01:51.878745031 -0400 -@@ -65,7 +65,7 @@ void cleanup_report_mod_passwd (void *cl - pw_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_USER_MGMT, Prog, - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -86,7 +86,7 @@ void cleanup_report_add_user_passwd (voi - SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to /etc/passwd", -+ "adding-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -105,8 +105,8 @@ void cleanup_report_add_user_shadow (voi - - SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to /etc/shadow", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "adding-shadow-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -125,7 +125,7 @@ void cleanup_unlock_passwd (unused void - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking passwd file", -+ audit_logger_message ("unlocking-passwd", - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -144,7 +144,7 @@ void cleanup_unlock_shadow (unused void - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking shadow file", -+ audit_logger_message ("unlocking-shadow", - SHADOW_AUDIT_FAILURE); - #endif - } -diff -urp shadow-4.1.5.1.orig/src/chage.c shadow-4.1.5.1/src/chage.c ---- shadow-4.1.5.1.orig/src/chage.c 2011-11-19 17:54:47.000000000 -0500 -+++ shadow-4.1.5.1/src/chage.c 2014-10-14 08:39:23.787884075 -0400 -@@ -126,9 +126,10 @@ static /*@noreturn@*/void fail_exit (int - - #ifdef WITH_AUDIT - if (E_SUCCESS != code) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change age", -- user_name, (unsigned int) user_uid, 0); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-age", -+ user_name, (unsigned int) user_uid, -+ SHADOW_AUDIT_FAILURE); - } - #endif - -@@ -873,11 +874,7 @@ int main (int argc, char **argv) - fprintf (stderr, _("%s: Permission denied.\n"), Prog); - fail_exit (E_NOPERM); - } --#ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "display aging info", -- user_name, (unsigned int) user_uid, 1); --#endif -+ /* Displaying fields is not of interest to audit */ - list_fields (); - fail_exit (E_SUCCESS); - } -@@ -896,41 +893,43 @@ int main (int argc, char **argv) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change all aging information", -- user_name, (unsigned int) user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-all-aging-information", -+ user_name, (unsigned int) user_uid, -+ SHADOW_AUDIT_SUCCESS); - } - #endif - } else { - #ifdef WITH_AUDIT - if (Mflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change max age", -- user_name, (unsigned int) user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-max-age", -+ user_name, (unsigned int) user_uid, -+ SHADOW_AUDIT_SUCCESS); - } - if (mflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change min age", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-min-age", - user_name, (unsigned int) user_uid, 1); - } - if (dflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change last change date", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-last-change-date", - user_name, (unsigned int) user_uid, 1); - } - if (Wflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change passwd warning", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-passwd-warning", - user_name, (unsigned int) user_uid, 1); - } - if (Iflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change inactive days", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-inactive-days", - user_name, (unsigned int) user_uid, 1); - } - if (Eflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change passwd expiration", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-passwd-expiration", - user_name, (unsigned int) user_uid, 1); - } - #endif -diff -urp shadow-4.1.5.1.orig/src/gpasswd.c shadow-4.1.5.1/src/gpasswd.c ---- shadow-4.1.5.1.orig/src/gpasswd.c 2014-09-13 15:45:54.989829559 -0400 -+++ shadow-4.1.5.1/src/gpasswd.c 2014-10-14 08:43:07.393861012 -0400 -@@ -137,7 +137,7 @@ static void usage (int status) - (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); - (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); - (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); -- (void) fputs (_(" -r, --remove-password remove the GROUP's password\n"), usageout); -+ (void) fputs (_(" -r, --delete-password remove the GROUP's password\n"), usageout); - (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); - (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); - #ifdef SHADOWGRP -@@ -397,21 +397,14 @@ static void open_files (void) - - static void log_gpasswd_failure (const char *suffix) - { --#ifdef WITH_AUDIT -- char buf[1024]; --#endif - if (aflg) { - SYSLOG ((LOG_ERR, - "%s failed to add user %s to group %s%s", - myname, user, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to add user %s to group %s%s", -- myname, user, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (dflg) { -@@ -419,13 +412,9 @@ static void log_gpasswd_failure (const c - "%s failed to remove user %s from group %s%s", - myname, user, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to remove user %s from group %s%s", -- myname, user, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (rflg) { -@@ -433,13 +422,9 @@ static void log_gpasswd_failure (const c - "%s failed to remove password of group %s%s", - myname, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to remove password of group %s%s", -- myname, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "delete-group-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (Rflg) { -@@ -447,13 +432,9 @@ static void log_gpasswd_failure (const c - "%s failed to restrict access to group %s%s", - myname, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to restrict access to group %s%s", -- myname, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "restrict-group", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (Aflg || Mflg) { -@@ -463,13 +444,9 @@ static void log_gpasswd_failure (const c - "%s failed to set the administrators of group %s to %s%s", - myname, group, admins, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to set the administrators of group %s to %s%s", -- myname, group, admins, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "set-admins-of-group", -+ admins, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -479,13 +456,9 @@ static void log_gpasswd_failure (const c - "%s failed to set the members of group %s to %s%s", - myname, group, members, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to set the members of group %s to %s%s", -- myname, group, members, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-users-to-group", -+ members, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -494,13 +467,9 @@ static void log_gpasswd_failure (const c - "%s failed to change password of group %s%s", - myname, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to change password of group %s%s", -- myname, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "change-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -531,21 +500,14 @@ static void log_gpasswd_failure_gshadow - - static void log_gpasswd_success (const char *suffix) - { --#ifdef WITH_AUDIT -- char buf[1024]; --#endif - if (aflg) { - SYSLOG ((LOG_INFO, - "user %s added by %s to group %s%s", - user, myname, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "user %s added by %s to group %s%s", -- user, myname, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (dflg) { -@@ -553,13 +515,9 @@ static void log_gpasswd_success (const c - "user %s removed by %s from group %s%s", - user, myname, group, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "user %s removed by %s from group %s%s", -- user, myname, group, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (rflg) { -@@ -567,13 +525,9 @@ static void log_gpasswd_success (const c - "password of group %s removed by %s%s", - group, myname, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "password of group %s removed by %s%s", -- group, myname, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "delete-group-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (Rflg) { -@@ -581,13 +535,9 @@ static void log_gpasswd_success (const c - "access to group %s restricted by %s%s", - group, myname, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "access to group %s restricted by %s%s", -- group, myname, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "restrict-group", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (Aflg || Mflg) { -@@ -597,13 +547,9 @@ static void log_gpasswd_success (const c - "administrators of group %s set by %s to %s%s", - group, myname, admins, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "administrators of group %s set by %s to %s%s", -- group, myname, admins, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "set-admins-of-group", -+ admins, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } -@@ -613,13 +559,9 @@ static void log_gpasswd_success (const c - "members of group %s set by %s to %s%s", - group, myname, members, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "members of group %s set by %s to %s%s", -- group, myname, members, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-users-to-group", -+ members, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } -@@ -628,13 +570,9 @@ static void log_gpasswd_success (const c - "password of group %s changed by %s%s", - group, myname, suffix)); - #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "password of group %s changed by %s%s", -- group, myname, suffix); -- buf[1023] = '\0'; -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "change-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } -diff -urp shadow-4.1.5.1.orig/src/groupadd.c shadow-4.1.5.1/src/groupadd.c ---- shadow-4.1.5.1.orig/src/groupadd.c 2011-11-18 16:23:30.000000000 -0500 -+++ shadow-4.1.5.1/src/groupadd.c 2014-10-14 08:39:23.800884073 -0400 -@@ -127,6 +127,15 @@ static /*@noreturn@*/void usage (int sta - exit (status); - } - -+static void fail_exit(int status) -+{ -+#ifdef WITH_AUDIT -+ audit_logger(AUDIT_ADD_GROUP, Prog, "add-group", group_name, -+ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -+#endif -+ exit (status); -+} -+ - /* - * new_grent - initialize the values in a group file entry - * -@@ -210,7 +219,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), grp.gr_name); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP - /* -@@ -220,7 +229,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), sgrp.sg_name); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #endif /* SHADOWGRP */ - } -@@ -244,7 +253,7 @@ static void check_new_name (void) - fprintf (stderr, _("%s: '%s' is not a valid group name\n"), - Prog, group_name); - -- exit (E_BAD_ARG); -+ fail_exit (E_BAD_ARG); - } - - /* -@@ -260,11 +269,11 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group to /etc/group", -+ "add-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -282,11 +291,11 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group to /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "add-shadow-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -300,12 +309,6 @@ static void close_files (void) - #endif /* SHADOWGRP */ - - /* Report success at the system level */ --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "", -- group_name, (unsigned int) group_id, -- SHADOW_AUDIT_SUCCESS); --#endif - SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", - group_name, (unsigned int) group_id)); - del_cleanup (cleanup_report_add_group); -@@ -323,7 +326,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_group, NULL); - -@@ -333,7 +336,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_gshadow, NULL); - } -@@ -349,7 +352,7 @@ static void open_files (void) - if (gr_open (O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef SHADOWGRP -@@ -359,7 +362,7 @@ static void open_files (void) - _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -489,7 +492,7 @@ static void check_flags (void) - fprintf (stderr, - _("%s: group '%s' already exists\n"), - Prog, group_name); -- exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE); - } - - if (gflg && (getgrgid (group_id) != NULL)) { -@@ -508,7 +511,7 @@ static void check_flags (void) - fprintf (stderr, - _("%s: GID '%lu' already exists\n"), - Prog, (unsigned long int) group_id); -- exit (E_GID_IN_USE); -+ fail_exit (E_GID_IN_USE); - } - } - } -@@ -536,7 +539,7 @@ static void check_perms (void) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); -@@ -556,7 +559,7 @@ static void check_perms (void) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- exit (1); -+ fail_exit (1); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -588,7 +591,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot setup cleanup service.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - /* -@@ -610,7 +613,7 @@ int main (int argc, char **argv) - - if (!gflg) { - if (find_new_gid (rflg, &group_id, NULL) < 0) { -- exit (E_GID_IN_USE); -+ fail_exit (E_GID_IN_USE); - } - } - -diff -urp shadow-4.1.5.1.orig/src/groupdel.c shadow-4.1.5.1/src/groupdel.c ---- shadow-4.1.5.1.orig/src/groupdel.c 2011-11-18 16:23:30.000000000 -0500 -+++ shadow-4.1.5.1/src/groupdel.c 2014-10-14 08:39:23.801884073 -0400 -@@ -100,6 +100,15 @@ static /*@noreturn@*/void usage (int sta - exit (status); - } - -+static void fail_exit(int status) -+{ -+#ifdef WITH_AUDIT -+ audit_logger(AUDIT_GRP_MGMT, Prog, "delete-group", group_name, -+ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -+#endif -+ exit (status); -+} -+ - /* - * grp_update - update group file entries - * -@@ -126,7 +135,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, group_name, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef SHADOWGRP -@@ -138,7 +147,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, group_name, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -157,12 +166,12 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_GROUP, Prog, -- "removing group from /etc/group", -+ "delete-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -182,12 +191,12 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "removing group from /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "delete-shadow-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -201,13 +210,6 @@ static void close_files (void) - } - #endif /* SHADOWGRP */ - -- /* Report success at the system level */ --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "", -- group_name, (unsigned int) group_id, -- SHADOW_AUDIT_SUCCESS); --#endif - SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); - del_cleanup (cleanup_report_del_group); - } -@@ -224,7 +226,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_group, NULL); - #ifdef SHADOWGRP -@@ -233,7 +235,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_gshadow, NULL); - } -@@ -251,7 +253,7 @@ static void open_files (void) - _("%s: cannot open %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP - if (is_shadow_grp) { -@@ -260,7 +262,7 @@ static void open_files (void) - _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -301,7 +303,7 @@ static void group_busy (gid_t gid) - fprintf (stderr, - _("%s: cannot remove the primary group of user '%s'\n"), - Prog, pwd->pw_name); -- exit (E_GROUP_BUSY); -+ fail_exit (E_GROUP_BUSY); - } - - /* -@@ -379,7 +381,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot setup cleanup service.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - process_flags (argc, argv); -@@ -393,7 +395,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh); -@@ -414,7 +416,7 @@ int main (int argc, char **argv) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- exit (1); -+ fail_exit (1); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -434,7 +436,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: group '%s' does not exist\n"), - Prog, group_name); -- exit (E_NOTFOUND); -+ fail_exit (E_NOTFOUND); - } - - group_id = grp->gr_gid; -@@ -458,7 +460,7 @@ int main (int argc, char **argv) - _("%s: %s is the NIS master\n"), - Prog, nis_master); - } -- exit (E_NOTFOUND); -+ fail_exit (E_NOTFOUND); - } - #endif - -diff -urp shadow-4.1.5.1.orig/src/groupmod.c shadow-4.1.5.1/src/groupmod.c ---- shadow-4.1.5.1.orig/src/groupmod.c 2011-11-18 16:23:30.000000000 -0500 -+++ shadow-4.1.5.1/src/groupmod.c 2014-10-14 08:49:28.517821702 -0400 -@@ -438,7 +438,7 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_group.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -461,7 +461,7 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_gshadow.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -484,7 +484,7 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_passwd.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -499,8 +499,8 @@ static void close_files (void) - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -- "modifying group", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "modify-group", - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -512,6 +512,8 @@ static void close_files (void) - */ - static void prepare_failure_reports (void) - { -+ char *nv_pair, nv[64]; -+ - info_group.name = group_name; - #ifdef SHADOWGRP - info_gshadow.name = group_name; -@@ -524,76 +526,106 @@ static void prepare_failure_reports (voi - #endif - info_passwd.audit_msg = xmalloc (512); - -- (void) snprintf (info_group.audit_msg, 511, -- "changing %s; ", gr_dbname ()); -+ info_group.action = xmalloc (512); - #ifdef SHADOWGRP -- (void) snprintf (info_gshadow.audit_msg, 511, -- "changing %s; ", sgr_dbname ()); -+ info_gshadow.action = xmalloc (512); - #endif -- (void) snprintf (info_passwd.audit_msg, 511, -- "changing %s; ", pw_dbname ()); -+ info_passwd.action = xmalloc (512); - -- info_group.action = info_group.audit_msg -- + strlen (info_group.audit_msg); -+ (void) snprintf (info_group.audit_msg, 511, -+ "changing-group"); - #ifdef SHADOWGRP -- info_gshadow.action = info_gshadow.audit_msg -- + strlen (info_gshadow.audit_msg); -+ (void) snprintf (info_gshadow.audit_msg, 511, -+ "changing-shadow-group"); - #endif -- info_passwd.action = info_passwd.audit_msg -- + strlen (info_passwd.audit_msg); -+ (void) snprintf (info_passwd.audit_msg, 511, -+ "changing-group-passwd"); - -+ nv_pair = audit_encode_nv_string(" grp", group_name, -+ strlen(group_name)); -+ if(nv_pair) { -+ strncat(info_group.audit_msg, nv_pair, -+ 511 - strlen(info_group.audit_msg)); -+#ifdef SHADOWGRP -+ strncat(info_gshadow.audit_msg, nv_pair, -+ 511 - strlen(info_gshadow.audit_msg)); -+#endif -+ strncat(info_passwd.audit_msg, nv_pair, -+ 511 - strlen(info_passwd.audit_msg)); -+ free(nv_pair); -+ } -+ snprintf(nv, sizeof(nv), " gid=%lu", (unsigned long)group_id); -+ strncat(info_group.audit_msg, nv, 511 - strlen(info_group.audit_msg)); -+ strncat(info_passwd.audit_msg, nv, 511 - strlen(info_passwd.audit_msg)); -+ - (void) snprintf (info_group.action, -- 511 - strlen (info_group.audit_msg), -+ 511, - "group %s/%lu", - group_name, (unsigned long int) group_id); - #ifdef SHADOWGRP - (void) snprintf (info_gshadow.action, -- 511 - strlen (info_group.audit_msg), -+ 511, - "group %s", group_name); - #endif - (void) snprintf (info_passwd.action, -- 511 - strlen (info_group.audit_msg), -+ 511, - "group %s/%lu", - group_name, (unsigned long int) group_id); - - if (nflg) { -+ nv_pair = audit_encode_nv_string(" new_group", group_newname, -+ strlen(group_newname)); -+ strncat(info_group.audit_msg, nv_pair, -+ 511 - strlen(info_group.audit_msg)); - strncat (info_group.action, ", new name: ", -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - strncat (info_group.action, group_newname, -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - - #ifdef SHADOWGRP -+ strncat(info_gshadow.audit_msg, nv_pair, -+ 511 - strlen(info_gshadow.audit_msg)); - strncat (info_gshadow.action, ", new name: ", -- 511 - strlen (info_gshadow.audit_msg)); -+ 511 - strlen (info_gshadow.action)); - strncat (info_gshadow.action, group_newname, -- 511 - strlen (info_gshadow.audit_msg)); -+ 511 - strlen (info_gshadow.action)); - #endif - -+ strncat(info_passwd.audit_msg, nv_pair, -+ 511 - strlen(info_passwd.audit_msg)); - strncat (info_passwd.action, ", new name: ", -- 511 - strlen (info_passwd.audit_msg)); -+ 511 - strlen (info_passwd.action)); - strncat (info_passwd.action, group_newname, -- 511 - strlen (info_passwd.audit_msg)); -+ 511 - strlen (info_passwd.action)); -+ free(nv_pair); - } - if (pflg) { -+ /* Note: audit doesn't want this value recorded */ - strncat (info_group.action, ", new password", -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - - #ifdef SHADOWGRP - strncat (info_gshadow.action, ", new password", -- 511 - strlen (info_gshadow.audit_msg)); -+ 511 - strlen (info_gshadow.action)); - #endif - } - if (gflg) { -+ snprintf(nv, sizeof(nv), " new_gid=%lu", (unsigned long)group_newid); -+ strncat(info_group.audit_msg, nv, -+ 511 - strlen(info_group.audit_msg)); -+ strncat(info_passwd.audit_msg, nv, -+ 511 - strlen(info_passwd.audit_msg)); -+ - strncat (info_group.action, ", new gid: ", -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - (void) snprintf (info_group.action+strlen (info_group.action), -- 511 - strlen (info_group.audit_msg), -+ 511 - strlen (info_group.action), - "%lu", (unsigned long int) group_newid); - - strncat (info_passwd.action, ", new gid: ", -- 511 - strlen (info_passwd.audit_msg)); -+ 511 - strlen (info_passwd.action)); - (void) snprintf (info_passwd.action+strlen (info_passwd.action), -- 511 - strlen (info_passwd.audit_msg), -+ 511 - strlen (info_passwd.action), - "%lu", (unsigned long int) group_newid); - } - info_group.audit_msg[511] = '\0'; -@@ -601,6 +633,11 @@ static void prepare_failure_reports (voi - info_gshadow.audit_msg[511] = '\0'; - #endif - info_passwd.audit_msg[511] = '\0'; -+ info_group.action[511] = '\0'; -+#ifdef SHADOWGRP -+ info_gshadow.action[511] = '\0'; -+#endif -+ info_passwd.action[511] = '\0'; - - // FIXME: add a system cleanup - add_cleanup (cleanup_report_mod_group, &info_group); -diff -urp shadow-4.1.5.1.orig/src/newgrp.c shadow-4.1.5.1/src/newgrp.c ---- shadow-4.1.5.1.orig/src/newgrp.c 2014-09-13 15:45:55.010829557 -0400 -+++ shadow-4.1.5.1/src/newgrp.c 2014-10-14 08:39:23.802884073 -0400 -@@ -197,11 +197,12 @@ static void check_perms (const struct gr - strcmp (cpasswd, grp->gr_passwd) != 0) { - #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "authentication new-gid=%lu", -+ "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); - audit_logger (AUDIT_GRP_AUTH, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); - #endif - SYSLOG ((LOG_INFO, - "Invalid password for group '%s' from '%s'", -@@ -212,11 +213,12 @@ static void check_perms (const struct gr - } - #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "authentication new-gid=%lu", -+ "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); - audit_logger (AUDIT_GRP_AUTH, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 1); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_SUCCESS); - #endif - } - -@@ -227,19 +229,6 @@ failure: - * harm. -- JWP - */ - closelog (); --#ifdef WITH_AUDIT -- if (groupname) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", groupname); -- audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, -- (unsigned int) getuid (), 0); -- } else { -- audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, -- (unsigned int) getuid (), 0); -- } --#endif - exit (EXIT_FAILURE); - } - -@@ -308,15 +297,27 @@ static void syslog_sg (const char *name, - is_newgrp ? "newgrp" : "sg", strerror (errno)); - #ifdef WITH_AUDIT - if (group) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", group); -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; -+ int len = strnlen(group, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(group, len)) { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=%s", -+ audit_encode_value(enc_group, -+ group, len)); -+ } else { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=\"%s\"", -+ group); -+ } - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -@@ -442,7 +443,7 @@ int main (int argc, char **argv) - #ifdef WITH_AUDIT - audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); - #endif - SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", - (unsigned long) getuid ())); -@@ -558,15 +559,26 @@ int main (int argc, char **argv) - perror ("getgroups"); - #ifdef WITH_AUDIT - if (group) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", group); -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; -+ int len = strnlen(group, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(group, len)) { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=%s", -+ audit_encode_value(enc_group, -+ group, len)); -+ } else { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=\"%s\"", group); -+ } - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -@@ -707,10 +719,10 @@ int main (int argc, char **argv) - perror ("setgid"); - #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "changing new-gid=%lu", (unsigned long) gid); -+ "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); - #endif - exit (EXIT_FAILURE); - } -@@ -719,10 +731,10 @@ int main (int argc, char **argv) - perror ("setuid"); - #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "changing new-gid=%lu", (unsigned long) gid); -+ "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); - #endif - exit (EXIT_FAILURE); - } -@@ -736,10 +748,10 @@ int main (int argc, char **argv) - execl (SHELL, "sh", "-c", command, (char *) 0); - #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "changing new-gid=%lu", (unsigned long) gid); -+ "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); - #endif - perror (SHELL); - exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); -@@ -803,11 +815,11 @@ int main (int argc, char **argv) - } - - #ifdef WITH_AUDIT -- snprintf (audit_buf, sizeof(audit_buf), "changing new-gid=%lu", -+ snprintf (audit_buf, sizeof(audit_buf), "changing new_gid=%lu", - (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 1); -+ (unsigned int) getuid (), SHADOW_AUDIT_SUCCESS); - #endif - /* - * Exec the login shell and go away. We are trying to get back to -@@ -831,15 +843,24 @@ int main (int argc, char **argv) - closelog (); - #ifdef WITH_AUDIT - if (NULL != group) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", group); -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; -+ int len = strnlen(group, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(group, len)) { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=%s", -+ audit_encode_value(enc_group, -+ group, len)); -+ } else { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=\"%s\"", group); -+ } - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -diff -urp shadow-4.1.5.1.orig/src/useradd.c shadow-4.1.5.1/src/useradd.c ---- shadow-4.1.5.1.orig/src/useradd.c 2014-09-13 15:45:54.957829561 -0400 -+++ shadow-4.1.5.1/src/useradd.c 2014-10-14 08:52:53.066800605 -0400 -@@ -205,6 +205,8 @@ static void create_mail (void); - */ - static void fail_exit (int code) - { -+ int type; -+ - if (home_added) { - if (rmdir (user_home) != 0) { - fprintf (stderr, -@@ -218,12 +220,6 @@ static void fail_exit (int code) - if (spw_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking shadow file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - } -@@ -231,12 +227,6 @@ static void fail_exit (int code) - if (pw_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking passwd file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - } -@@ -244,12 +234,6 @@ static void fail_exit (int code) - if (gr_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking group file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - } -@@ -258,20 +242,19 @@ static void fail_exit (int code) - if (sgr_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking gshadow file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - } - #endif - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -+ if (code == E_PW_UPDATE || code >= E_GRP_UPDATE) -+ type = AUDIT_USER_MGMT; -+ else -+ type = AUDIT_ADD_USER; -+ -+ audit_logger (type, Prog, -+ "add-user", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -578,7 +561,7 @@ static int set_defaults (void) - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USYS_CONFIG, Prog, -- "changing useradd defaults", -+ "changing-useradd-defaults", - NULL, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -848,12 +831,6 @@ static void grp_update (void) - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_GRP_UPDATE); /* XXX */ - } - -@@ -867,18 +844,12 @@ static void grp_update (void) - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), ngrp->gr_name); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user_name, AUDIT_NO_ID, ngrp->gr_name, - SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -923,12 +894,6 @@ static void grp_update (void) - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to shadow group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_GRP_UPDATE); /* XXX */ - } - -@@ -942,18 +907,13 @@ static void grp_update (void) - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), nsgrp->sg_name); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to shadow group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif -+ - fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to shadow group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-to-shadow-group", -+ user_name, AUDIT_NO_ID, nsgrp->sg_name, - SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -1296,7 +1256,7 @@ static void process_flags (int argc, cha - Prog, user_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -+ "add-user", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1385,7 +1345,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking shadow file", -+ "unlocking-shadow-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1398,7 +1358,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking passwd file", -+ "unlocking-passwd-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1410,7 +1370,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking group file", -+ "unlocking-group-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1424,7 +1384,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking gshadow file", -+ "unlocking-gshadow-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1584,7 +1544,7 @@ static void grp_add (void) - Prog, gr_dbname (), grp.gr_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group", -+ "add-group", - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1600,7 +1560,7 @@ static void grp_add (void) - Prog, sgr_dbname (), sgrp.sg_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group", -+ "add-group", - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1610,7 +1570,7 @@ static void grp_add (void) - SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group", -+ "add-group", - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -1725,17 +1685,11 @@ static void usr_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), spent.sp_namp); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding shadow password", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_PW_UPDATE); - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -+ "add-user", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -1771,12 +1725,6 @@ static void create_home (void) - fprintf (stderr, - _("%s: cannot create directory %s\n"), - Prog, user_home); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding home directory", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_HOMEDIR); - } - chown (user_home, user_id, user_gid); -@@ -1784,8 +1732,8 @@ static void create_home (void) - 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK)); - home_added = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "add-home-dir", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -1951,12 +1899,6 @@ int main (int argc, char **argv) - */ - if (getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ - fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_NAME_IN_USE); - } - -@@ -1972,12 +1914,6 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), - Prog, user_name); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_NAME_IN_USE); - } - } -@@ -2007,12 +1943,6 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: UID %lu is not unique\n"), - Prog, (unsigned long) user_id); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_UID_IN_USE); - } - } -@@ -2057,9 +1987,10 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), - Prog, user_name, user_selinux); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding SELinux user mapping", -- user_name, (unsigned int) user_id, 0); -+ audit_logger (AUDIT_ROLE_ASSIGN, Prog, -+ "add-selinux-user-mapping", -+ user_name, (unsigned int) user_id, -+ SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - rv = E_SE_UPDATE; - } -diff -urp shadow-4.1.5.1.orig/src/userdel.c shadow-4.1.5.1/src/userdel.c ---- shadow-4.1.5.1.orig/src/userdel.c 2014-09-13 15:45:55.001829558 -0400 -+++ shadow-4.1.5.1/src/userdel.c 2014-10-14 08:44:52.714850149 -0400 -@@ -201,9 +201,9 @@ static void update_groups (void) - * Update the DBM group file with the new entry as well. - */ - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user from group", -- user_name, (unsigned int) user_id, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "deleting-user-from-group", -+ user_name, (unsigned int) user_id, ngrp->gr_name, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", -@@ -263,9 +263,9 @@ static void update_groups (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user from shadow group", -- user_name, (unsigned int) user_id, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "deleting-user-from-shadow-group", -+ user_name, (unsigned int) user_id, nsgrp->sg_name, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", -@@ -342,9 +342,9 @@ static void remove_usergroup (void) - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "deleting group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_DEL_GROUP, Prog, -+ "delete-group", -+ user_name, AUDIT_NO_ID, user_name, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, -@@ -360,9 +360,9 @@ static void remove_usergroup (void) - fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "deleting shadow group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "delete-shadow-group", -+ user_name, AUDIT_NO_ID, user_name, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, -@@ -478,7 +478,7 @@ static void fail_exit (int code) - - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user", -+ "delete-user", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -498,24 +498,12 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - pw_locked = true; - if (pw_open (O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - if (is_shadow_pwd) { -@@ -523,12 +511,6 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking shadow password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - spw_locked = true; -@@ -536,12 +518,6 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening shadow password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - } -@@ -549,23 +525,11 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - gr_locked = true; - if (gr_open (O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP -@@ -574,24 +538,12 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking shadow group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - sgr_locked= true; - if (sgr_open (O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening shadow group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - } -@@ -622,7 +574,7 @@ static void update_user (void) - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user entries", -+ "delete-user", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ -@@ -716,7 +668,7 @@ static int remove_mailbox (void) - SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -732,7 +684,7 @@ static int remove_mailbox (void) - SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -742,8 +694,8 @@ static int remove_mailbox (void) - #ifdef WITH_AUDIT - else - { -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); - } -@@ -760,7 +712,7 @@ static int remove_mailbox (void) - mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -775,7 +727,7 @@ static int remove_mailbox (void) - SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -785,8 +737,8 @@ static int remove_mailbox (void) - #ifdef WITH_AUDIT - else - { -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); - } -@@ -980,7 +932,7 @@ int main (int argc, char **argv) - Prog, user_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user not found", -+ "deleting-user-not-found", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -1024,7 +976,7 @@ int main (int argc, char **argv) - if (!fflg) { - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user logged in", -+ "deleting-user-logged-in", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -1101,8 +1053,8 @@ int main (int argc, char **argv) - #ifdef WITH_AUDIT - else - { -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "deleting-home-directory", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); - } -@@ -1111,7 +1063,7 @@ int main (int argc, char **argv) - #ifdef WITH_AUDIT - if (0 != errors) { - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting home directory", -+ "deleting-home-directory", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - } -@@ -1124,8 +1076,8 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), - Prog, user_name); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "removing SELinux user mapping", -+ audit_logger (AUDIT_ROLE_REMOVE, Prog, -+ "delete-selinux-user-mapping", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -diff -urp shadow-4.1.5.1.orig/src/usermod.c shadow-4.1.5.1/src/usermod.c ---- shadow-4.1.5.1.orig/src/usermod.c 2014-09-13 15:45:55.013829557 -0400 -+++ shadow-4.1.5.1/src/usermod.c 2014-10-14 08:50:05.817817855 -0400 -@@ -352,8 +352,8 @@ static char *new_pw_passwd (char *pw_pas - - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating passwd", -- user_newname, (unsigned int) user_newid, 0); -+ "updating-password", -+ user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); - strcpy (buf, "!"); -@@ -372,8 +372,8 @@ static char *new_pw_passwd (char *pw_pas - - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating password", -- user_newname, (unsigned int) user_newid, 0); -+ "updating-password", -+ user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); - s = pw_pass; -@@ -384,7 +384,7 @@ static char *new_pw_passwd (char *pw_pas - } else if (pflg) { - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing password", -+ "updating-password", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); -@@ -413,8 +413,8 @@ static void new_pwent (struct passwd *pw - fail_exit (E_NAME_IN_USE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing name", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-name", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -434,8 +434,8 @@ static void new_pwent (struct passwd *pw - - if (uflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing uid", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-uid", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -445,8 +445,8 @@ static void new_pwent (struct passwd *pw - } - if (gflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing primary group", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-primary-group", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -456,8 +456,8 @@ static void new_pwent (struct passwd *pw - } - if (cflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing comment", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-comment", - user_newname, (unsigned int) user_newid, 1); - #endif - pwent->pw_gecos = user_newcomment; -@@ -465,8 +465,8 @@ static void new_pwent (struct passwd *pw - - if (dflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-home-dir", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -476,8 +476,8 @@ static void new_pwent (struct passwd *pw - } - if (sflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing user shell", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-shell", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -507,8 +507,8 @@ static void new_spent (struct spwd *spen - - if (fflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing inactive days", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-inactive-days", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -524,8 +524,8 @@ static void new_spent (struct spwd *spen - date_to_str (old_exp, sizeof(old_exp), - user_expire * DAY); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing expiration date", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-expiration-date", - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -592,9 +592,9 @@ static /*@noreturn@*/void fail_exit (int - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "modifying account", -- user_name, AUDIT_NO_ID, 0); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "modify-account", -+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); - #endif - exit (code); - } -@@ -648,9 +648,12 @@ static void update_group (void) - user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing group member", -- user_newname, AUDIT_NO_ID, 1); -+ audit_logger_with_group ( -+ AUDIT_USER_MGMT, Prog, -+ "update-member-in-group", -+ user_newname, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "change '%s' to '%s' in group '%s'", -@@ -664,9 +667,11 @@ static void update_group (void) - ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing group member", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user_name, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "delete '%s' from group '%s'", -@@ -679,9 +684,11 @@ static void update_group (void) - ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user_name, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "add '%s' to group '%s'", - user_newname, ngrp->gr_name)); -@@ -756,9 +763,10 @@ static void update_gshadow (void) - nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing admin name in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "update-admin-name-in-shadow-group", -+ user_name, AUDIT_NO_ID, nsgrp->sg_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "change admin '%s' to '%s' in shadow group '%s'", -@@ -778,9 +786,10 @@ static void update_gshadow (void) - user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing member in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "update-member-in-shadow-group", -+ user_name, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); - #endif - SYSLOG ((LOG_INFO, - "change '%s' to '%s' in shadow group '%s'", -@@ -794,9 +803,10 @@ static void update_gshadow (void) - nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing user from shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-shadow-group", -+ user_name, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); - #endif - SYSLOG ((LOG_INFO, - "delete '%s' from shadow group '%s'", -@@ -809,9 +819,10 @@ static void update_gshadow (void) - nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to shadow group", -- user_newname, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-shadow-group", -+ user_newname, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); - #endif - SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", - user_newname, nsgrp->sg_name)); -@@ -1515,8 +1526,8 @@ static void move_home (void) - - #ifdef WITH_AUDIT - if (uflg || gflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing home directory owner", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-home-dir-owner", - user_newname, (unsigned int) user_newid, 1); - } - #endif -@@ -1534,8 +1545,8 @@ static void move_home (void) - fail_exit (E_HOMEDIR); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "moving home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "moving-home-dir", - user_newname, (unsigned int) user_newid, - 1); - #endif -@@ -1554,9 +1565,9 @@ static void move_home (void) - Prog, user_home); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, -+ audit_logger (AUDIT_USER_MGMT, - Prog, -- "moving home directory", -+ "moving-home-dir", - user_newname, - (unsigned int) user_newid, - 1); -@@ -1760,8 +1771,8 @@ static void move_mailbox (void) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing mail file owner", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-mail-file-owner", - user_newname, (unsigned int) user_newid, 1); - } - #endif -@@ -1779,8 +1790,8 @@ static void move_mailbox (void) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing mail file name", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-mail-file-name", - user_newname, (unsigned int) user_newid, 1); - } - #endif -@@ -1910,8 +1921,8 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), - Prog, user_name, user_selinux); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "modifying User mapping ", -+ audit_logger (AUDIT_ROLE_ASSIGN, Prog, -+ "changing-selinux-user-mapping ", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -1923,8 +1934,8 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), - Prog, user_name); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "removing SELinux user mapping", -+ audit_logger (AUDIT_ROLE_REMOVE, Prog, -+ "delete-selinux-user-mapping", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -1962,8 +1973,8 @@ int main (int argc, char **argv) - */ - #ifdef WITH_AUDIT - if (uflg || gflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing home directory owner", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-home-dir-owner", - user_newname, (unsigned int) user_newid, 1); - } - #endif diff --git a/SOURCES/shadow-4.1.5.1-backup-mode.patch b/SOURCES/shadow-4.1.5.1-backup-mode.patch deleted file mode 100644 index 7366b86..0000000 --- a/SOURCES/shadow-4.1.5.1-backup-mode.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff -up shadow-4.1.5.1/lib/commonio.c.backup-mode shadow-4.1.5.1/lib/commonio.c ---- shadow-4.1.5.1/lib/commonio.c.backup-mode 2012-05-18 21:44:54.000000000 +0200 -+++ shadow-4.1.5.1/lib/commonio.c 2012-09-19 20:27:16.089444234 +0200 -@@ -301,15 +301,12 @@ static int create_backup (const char *ba - struct utimbuf ub; - FILE *bkfp; - int c; -- mode_t mask; - - if (fstat (fileno (fp), &sb) != 0) { - return -1; - } - -- mask = umask (077); -- bkfp = fopen (backup, "w"); -- (void) umask (mask); -+ bkfp = fopen_set_perms (backup, "w", &sb); - if (NULL == bkfp) { - return -1; - } diff --git a/SOURCES/shadow-4.1.5.1-chgrp-guard.patch b/SOURCES/shadow-4.1.5.1-chgrp-guard.patch deleted file mode 100644 index 220884c..0000000 --- a/SOURCES/shadow-4.1.5.1-chgrp-guard.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff -up shadow-4.1.5.1/man/usermod.8.xml.chgrp-guard shadow-4.1.5.1/man/usermod.8.xml ---- shadow-4.1.5.1/man/usermod.8.xml.chgrp-guard 2016-05-04 13:44:17.267917583 +0200 -+++ shadow-4.1.5.1/man/usermod.8.xml 2016-05-04 13:44:17.284917968 +0200 -@@ -198,6 +198,12 @@ - The group ownership of files outside of the user's home directory - must be fixed manually. - -+ -+ The change of the group ownership of files inside of the user's -+ home directory is also not done if the home dir owner uid is -+ different from the current or new user id. This is safety measure -+ for special home directories such as /. -+ - - - -@@ -364,6 +370,12 @@ - must be fixed manually. - - -+ The change of the user ownership of files inside of the user's -+ home directory is also not done if the home dir owner uid is -+ different from the current or new user id. This is safety measure -+ for special home directories such as /. -+ -+ - No checks will be performed with regard to the - , , - , or -diff -up shadow-4.1.5.1/src/usermod.c.chgrp-guard shadow-4.1.5.1/src/usermod.c ---- shadow-4.1.5.1/src/usermod.c.chgrp-guard 2016-05-04 13:44:17.280917877 +0200 -+++ shadow-4.1.5.1/src/usermod.c 2016-05-04 13:44:17.285917991 +0200 -@@ -1971,7 +1971,10 @@ int main (int argc, char **argv) - } - - if (!mflg && (uflg || gflg)) { -- if (access (dflg ? user_newhome : user_home, F_OK) == 0) { -+ struct stat sb; -+ -+ if (stat (dflg ? user_newhome : user_home, &sb) == 0 && -+ ((uflg && sb.st_uid == user_newid) || sb.st_uid == user_id)) { - /* - * Change the UID on all of the files owned by - * `user_id' to `user_newid' in the user's home diff --git a/SOURCES/shadow-4.1.5.1-crypt-null.patch b/SOURCES/shadow-4.1.5.1-crypt-null.patch deleted file mode 100644 index fba72e7..0000000 --- a/SOURCES/shadow-4.1.5.1-crypt-null.patch +++ /dev/null @@ -1,195 +0,0 @@ -diff -up shadow-4.1.5.1/lib/encrypt.c.crypt-null shadow-4.1.5.1/lib/encrypt.c ---- shadow-4.1.5.1/lib/encrypt.c.crypt-null 2010-08-22 15:05:02.000000000 +0200 -+++ shadow-4.1.5.1/lib/encrypt.c 2013-07-25 12:27:30.438355782 +0200 -@@ -49,11 +49,10 @@ - if (!cp) { - /* - * Single Unix Spec: crypt() may return a null pointer, -- * and set errno to indicate an error. The caller doesn't -- * expect us to return NULL, so... -+ * and set errno to indicate an error. In this case return -+ * the NULL so the caller can handle appropriately. - */ -- perror ("crypt"); -- exit (EXIT_FAILURE); -+ return cp; - } - - /* The GNU crypt does not return NULL if the algorithm is not -diff -up shadow-4.1.5.1/libmisc/valid.c.crypt-null shadow-4.1.5.1/libmisc/valid.c ---- shadow-4.1.5.1/libmisc/valid.c.crypt-null 2010-08-22 21:14:41.000000000 +0200 -+++ shadow-4.1.5.1/libmisc/valid.c 2013-07-25 12:27:30.440355847 +0200 -@@ -95,6 +95,7 @@ bool valid (const char *password, const - */ - - if ( (NULL != ent->pw_name) -+ && (NULL != encrypted) - && (strcmp (encrypted, ent->pw_passwd) == 0)) { - return true; - } else { -diff -up shadow-4.1.5.1/lib/pwauth.c.crypt-null shadow-4.1.5.1/lib/pwauth.c ---- shadow-4.1.5.1/lib/pwauth.c.crypt-null 2009-07-13 00:24:48.000000000 +0200 -+++ shadow-4.1.5.1/lib/pwauth.c 2013-07-25 12:27:30.438355782 +0200 -@@ -73,6 +73,7 @@ int pw_auth (const char *cipher, - char prompt[1024]; - char *clear = NULL; - const char *cp; -+ const char *encrypted; - int retval; - - #ifdef SKEY -@@ -177,7 +178,11 @@ int pw_auth (const char *cipher, - * the results there as well. - */ - -- retval = strcmp (pw_encrypt (input, cipher), cipher); -+ encrypted = pw_encrypt (input, cipher); -+ if (encrypted!=NULL) -+ retval = strcmp (encrypted, cipher); -+ else -+ retval = -1; - - #ifdef SKEY - /* -diff -up shadow-4.1.5.1/src/chgpasswd.c.crypt-null shadow-4.1.5.1/src/chgpasswd.c ---- shadow-4.1.5.1/src/chgpasswd.c.crypt-null 2011-12-09 22:31:40.000000000 +0100 -+++ shadow-4.1.5.1/src/chgpasswd.c 2013-07-25 12:27:30.440355847 +0200 -@@ -469,6 +469,10 @@ int main (int argc, char **argv) - #endif - cp = pw_encrypt (newpwd, - crypt_make_salt (crypt_method, arg)); -+ if (cp == NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } - } - - /* -diff -up shadow-4.1.5.1/src/chpasswd.c.crypt-null shadow-4.1.5.1/src/chpasswd.c ---- shadow-4.1.5.1/src/chpasswd.c.crypt-null 2011-12-09 22:31:40.000000000 +0100 -+++ shadow-4.1.5.1/src/chpasswd.c 2013-07-25 12:27:30.440355847 +0200 -@@ -492,6 +492,10 @@ int main (int argc, char **argv) - #endif - cp = pw_encrypt (newpwd, - crypt_make_salt(crypt_method, arg)); -+ if (cp == NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } - } - - /* -diff -up shadow-4.1.5.1/src/gpasswd.c.crypt-null shadow-4.1.5.1/src/gpasswd.c ---- shadow-4.1.5.1/src/gpasswd.c.crypt-null 2011-11-19 23:55:04.000000000 +0100 -+++ shadow-4.1.5.1/src/gpasswd.c 2013-07-25 12:27:30.441355866 +0200 -@@ -939,6 +939,10 @@ static void change_passwd (struct group - } - - cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL)); -+ if (cp==NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } - memzero (pass, sizeof pass); - #ifdef SHADOWGRP - if (is_shadowgrp) { -diff -up shadow-4.1.5.1/src/newgrp.c.crypt-null shadow-4.1.5.1/src/newgrp.c ---- shadow-4.1.5.1/src/newgrp.c.crypt-null 2011-07-30 03:50:01.000000000 +0200 -+++ shadow-4.1.5.1/src/newgrp.c 2013-07-25 12:27:30.442355881 +0200 -@@ -184,7 +184,8 @@ static void check_perms (const struct gr - cpasswd = pw_encrypt (cp, grp->gr_passwd); - strzero (cp); - -- if (grp->gr_passwd[0] == '\0' || -+ if (cpasswd == NULL || -+ grp->gr_passwd[0] == '\0' || - strcmp (cpasswd, grp->gr_passwd) != 0) { - #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -diff -up shadow-4.1.5.1/src/newusers.c.crypt-null shadow-4.1.5.1/src/newusers.c ---- shadow-4.1.5.1/src/newusers.c.crypt-null 2011-12-09 22:31:40.000000000 +0100 -+++ shadow-4.1.5.1/src/newusers.c 2013-07-25 12:27:30.442355881 +0200 -@@ -387,6 +387,7 @@ static int add_user (const char *name, u - static void update_passwd (struct passwd *pwd, const char *password) - { - void *crypt_arg = NULL; -+ char *cp; - if (crypt_method != NULL) { - #ifdef USE_SHA_CRYPT - if (sflg) { -@@ -398,9 +399,13 @@ static void update_passwd (struct passwd - if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { - pwd->pw_passwd = (char *)password; - } else { -- pwd->pw_passwd = pw_encrypt (password, -- crypt_make_salt (crypt_method, -- crypt_arg)); -+ cp=pw_encrypt (password, crypt_make_salt (crypt_method, -+ crypt_arg)); -+ if (cp == NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } -+ pwd->pw_passwd = cp; - } - } - #endif /* !USE_PAM */ -@@ -412,6 +417,7 @@ static int add_passwd (struct passwd *pw - { - const struct spwd *sp; - struct spwd spent; -+ char *cp; - - #ifndef USE_PAM - void *crypt_arg = NULL; -@@ -448,7 +454,12 @@ static int add_passwd (struct passwd *pw - } else { - const char *salt = crypt_make_salt (crypt_method, - crypt_arg); -- spent.sp_pwdp = pw_encrypt (password, salt); -+ cp = pw_encrypt (password, salt); -+ if (cp == NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } -+ spent.sp_pwdp = cp; - } - spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE; - if (0 == spent.sp_lstchg) { -@@ -492,7 +503,12 @@ static int add_passwd (struct passwd *pw - spent.sp_pwdp = (char *)password; - } else { - const char *salt = crypt_make_salt (crypt_method, crypt_arg); -- spent.sp_pwdp = pw_encrypt (password, salt); -+ cp = pw_encrypt (password, salt); -+ if (cp == NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } -+ spent.sp_pwdp = cp; - } - #else - /* -diff -up shadow-4.1.5.1/src/passwd.c.crypt-null shadow-4.1.5.1/src/passwd.c ---- shadow-4.1.5.1/src/passwd.c.crypt-null 2012-02-13 21:32:01.000000000 +0100 -+++ shadow-4.1.5.1/src/passwd.c 2013-07-25 12:27:30.443355896 +0200 -@@ -242,7 +242,7 @@ static int new_password (const struct pa - } - - cipher = pw_encrypt (clear, crypt_passwd); -- if (strcmp (cipher, crypt_passwd) != 0) { -+ if ((cipher == NULL) || (strcmp (cipher, crypt_passwd) != 0)) { - strzero (clear); - strzero (cipher); - SYSLOG ((LOG_WARN, "incorrect password for %s", -@@ -349,6 +349,10 @@ static int new_password (const struct pa - * Encrypt the password, then wipe the cleartext password. - */ - cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL)); -+ if (cp == NULL) { -+ perror ("crypt"); -+ exit (EXIT_FAILURE); -+ } - memzero (pass, sizeof pass); - - #ifdef HAVE_LIBCRACK_HIST diff --git a/SOURCES/shadow-4.1.5.1-date-parsing.patch b/SOURCES/shadow-4.1.5.1-date-parsing.patch deleted file mode 100644 index 38ec091..0000000 --- a/SOURCES/shadow-4.1.5.1-date-parsing.patch +++ /dev/null @@ -1,138 +0,0 @@ -diff -up shadow-4.1.5.1/libmisc/getdate.c.date-parsing shadow-4.1.5.1/libmisc/getdate.c ---- shadow-4.1.5.1/libmisc/getdate.c.date-parsing 2008-06-14 00:07:51.000000000 +0200 -+++ shadow-4.1.5.1/libmisc/getdate.c 2014-08-29 13:41:22.553267506 +0200 -@@ -261,6 +261,7 @@ static int yyHaveDay; - static int yyHaveRel; - static int yyHaveTime; - static int yyHaveZone; -+static int yyHaveYear; - static int yyTimezone; - static int yyDay; - static int yyHour; -@@ -1730,6 +1731,7 @@ yyreduce: - yyDay = (yyvsp[(3) - (5)].Number); - yyYear = (yyvsp[(5) - (5)].Number); - } -+ yyHaveYear++; - } - break; - -@@ -1740,6 +1742,7 @@ yyreduce: - yyYear = (yyvsp[(1) - (3)].Number); - yyMonth = -(yyvsp[(2) - (3)].Number); - yyDay = -(yyvsp[(3) - (3)].Number); -+ yyHaveYear++; - } - break; - -@@ -1750,6 +1753,7 @@ yyreduce: - yyDay = (yyvsp[(1) - (3)].Number); - yyMonth = (yyvsp[(2) - (3)].Number); - yyYear = -(yyvsp[(3) - (3)].Number); -+ yyHaveYear++; - } - break; - -@@ -1767,6 +1771,7 @@ yyreduce: - yyMonth = (yyvsp[(1) - (4)].Number); - yyDay = (yyvsp[(2) - (4)].Number); - yyYear = (yyvsp[(4) - (4)].Number); -+ yyHaveYear++; - } - break; - -@@ -1784,6 +1789,7 @@ yyreduce: - yyMonth = (yyvsp[(2) - (3)].Number); - yyDay = (yyvsp[(1) - (3)].Number); - yyYear = (yyvsp[(3) - (3)].Number); -+ yyHaveYear++; - } - break; - -@@ -1928,7 +1934,8 @@ yyreduce: - case 49: - #line 397 "getdate.y" - { -- if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0)) -+ if ((yyHaveTime != 0 || (yyvsp[(1) - (1)].Number) >= 100) && !yyHaveYear -+ && (yyHaveDate != 0) && (yyHaveRel == 0)) - yyYear = (yyvsp[(1) - (1)].Number); - else - { -@@ -2556,7 +2563,7 @@ yylex (void) - return LookupWord (buff); - } - if (c != '(') -- return *yyInput++; -+ return (unsigned char)*yyInput++; - Count = 0; - do - { -diff -up shadow-4.1.5.1/libmisc/getdate.y.date-parsing shadow-4.1.5.1/libmisc/getdate.y ---- shadow-4.1.5.1/libmisc/getdate.y.date-parsing 2008-05-26 10:57:51.000000000 +0200 -+++ shadow-4.1.5.1/libmisc/getdate.y 2014-08-29 13:40:37.502229879 +0200 -@@ -152,6 +152,7 @@ static int yyHaveDay; - static int yyHaveRel; - static int yyHaveTime; - static int yyHaveZone; -+static int yyHaveYear; - static int yyTimezone; - static int yyDay; - static int yyHour; -@@ -293,18 +294,21 @@ date : tUNUMBER '/' tUNUMBER { - yyDay = $3; - yyYear = $5; - } -+ yyHaveYear++; - } - | tUNUMBER tSNUMBER tSNUMBER { - /* ISO 8601 format. yyyy-mm-dd. */ - yyYear = $1; - yyMonth = -$2; - yyDay = -$3; -+ yyHaveYear++; - } - | tUNUMBER tMONTH tSNUMBER { - /* e.g. 17-JUN-1992. */ - yyDay = $1; - yyMonth = $2; - yyYear = -$3; -+ yyHaveYear++; - } - | tMONTH tUNUMBER { - yyMonth = $1; -@@ -314,6 +318,7 @@ date : tUNUMBER '/' tUNUMBER { - yyMonth = $1; - yyDay = $2; - yyYear = $4; -+ yyHaveYear++; - } - | tUNUMBER tMONTH { - yyMonth = $2; -@@ -323,6 +328,7 @@ date : tUNUMBER '/' tUNUMBER { - yyMonth = $2; - yyDay = $1; - yyYear = $3; -+ yyHaveYear++; - } - ; - -@@ -395,7 +401,8 @@ relunit : tUNUMBER tYEAR_UNIT { - - number : tUNUMBER - { -- if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0)) -+ if ((yyHaveTime != 0 || $1 >= 100) && !yyHaveYear -+ && (yyHaveDate != 0) && (yyHaveRel == 0)) - yyYear = $1; - else - { -@@ -802,7 +809,7 @@ yylex (void) - return LookupWord (buff); - } - if (c != '(') -- return *yyInput++; -+ return (unsigned char)*yyInput++; - Count = 0; - do - { diff --git a/SOURCES/shadow-4.1.5.1-default-range.patch b/SOURCES/shadow-4.1.5.1-default-range.patch index 45c677a..2a9d640 100644 --- a/SOURCES/shadow-4.1.5.1-default-range.patch +++ b/SOURCES/shadow-4.1.5.1-default-range.patch @@ -1,6 +1,7 @@ -diff -up shadow-4.1.5.1/lib/semanage.c.default-range shadow-4.1.5.1/lib/semanage.c ---- shadow-4.1.5.1/lib/semanage.c.default-range 2012-01-08 17:35:44.000000000 +0100 -+++ shadow-4.1.5.1/lib/semanage.c 2013-06-14 15:14:51.970237594 +0200 +Index: shadow-4.5/lib/semanage.c +=================================================================== +--- shadow-4.5.orig/lib/semanage.c ++++ shadow-4.5/lib/semanage.c @@ -143,6 +143,7 @@ static int semanage_user_mod (semanage_h goto done; } diff --git a/SOURCES/shadow-4.1.5.1-errmsg.patch b/SOURCES/shadow-4.1.5.1-errmsg.patch deleted file mode 100644 index 6f3a1d2..0000000 --- a/SOURCES/shadow-4.1.5.1-errmsg.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -up shadow-4.1.5.1/src/useradd.c.logmsg shadow-4.1.5.1/src/useradd.c ---- shadow-4.1.5.1/src/useradd.c.logmsg 2013-02-20 15:41:44.000000000 +0100 -+++ shadow-4.1.5.1/src/useradd.c 2013-06-14 14:22:59.529661095 +0200 -@@ -1760,6 +1760,9 @@ static void create_home (void) - if (access (user_home, F_OK) != 0) { - #ifdef WITH_SELINUX - if (set_selinux_file_context (user_home, NULL) != 0) { -+ fprintf (stderr, -+ _("%s: cannot set SELinux context for home directory %s\n"), -+ Prog, user_home); - fail_exit (E_HOMEDIR); - } - #endif -@@ -1789,6 +1792,9 @@ static void create_home (void) - #ifdef WITH_SELINUX - /* Reset SELinux to create files with default contexts */ - if (reset_selinux_file_context () != 0) { -+ fprintf (stderr, -+ _("%s: cannot reset SELinux file creation context\n"), -+ Prog); - fail_exit (E_HOMEDIR); - } - #endif diff --git a/SOURCES/shadow-4.1.5.1-goodname.patch b/SOURCES/shadow-4.1.5.1-goodname.patch deleted file mode 100644 index 2bbf38a..0000000 --- a/SOURCES/shadow-4.1.5.1-goodname.patch +++ /dev/null @@ -1,113 +0,0 @@ -diff -up shadow-4.1.5.1/libmisc/chkname.c.goodname shadow-4.1.5.1/libmisc/chkname.c ---- shadow-4.1.5.1/libmisc/chkname.c.goodname 2009-07-13 00:24:45.000000000 +0200 -+++ shadow-4.1.5.1/libmisc/chkname.c 2018-04-24 16:32:40.970529916 +0200 -@@ -49,25 +49,44 @@ - static bool is_valid_name (const char *name) - { - /* -- * User/group names must match [a-z_][a-z0-9_-]*[$] -- */ -- if (('\0' == *name) || -- !((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) { -+ * User/group names must match gnu e-regex: -+ * [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]? -+ * -+ * as a non-POSIX, extension, allow "$" as the last char for -+ * sake of Samba 3.x "add machine script" -+ * -+ * Also do not allow fully numeric names or just "." or "..". -+ */ -+ int numeric; -+ -+ if ('\0' == *name || -+ ('.' == *name && (('.' == name[1] && '\0' == name[2]) || -+ '\0' == name[1])) || -+ !((*name >= 'a' && *name <= 'z') || -+ (*name >= 'A' && *name <= 'Z') || -+ (*name >= '0' && *name <= '9') || -+ *name == '_' || -+ *name == '.')) { - return false; - } - -+ numeric = isdigit(*name); -+ - while ('\0' != *++name) { -- if (!(( ('a' <= *name) && ('z' >= *name) ) || -- ( ('0' <= *name) && ('9' >= *name) ) || -- ('_' == *name) || -- ('-' == *name) || -- ( ('$' == *name) && ('\0' == *(name + 1)) ) -+ if (!((*name >= 'a' && *name <= 'z') || -+ (*name >= 'A' && *name <= 'Z') || -+ (*name >= '0' && *name <= '9') || -+ *name == '_' || -+ *name == '.' || -+ *name == '-' || -+ (*name == '$' && name[1] == '\0') - )) { - return false; - } -+ numeric &= isdigit(*name); - } - -- return true; -+ return !numeric || getenv("SHADOW_ALLOW_ALL_NUMERIC_USER") != NULL; - } - - bool is_valid_user_name (const char *name) -diff -up shadow-4.1.5.1/man/groupadd.8.xml.goodname shadow-4.1.5.1/man/groupadd.8.xml ---- shadow-4.1.5.1/man/groupadd.8.xml.goodname 2012-05-25 13:45:27.000000000 +0200 -+++ shadow-4.1.5.1/man/groupadd.8.xml 2012-09-19 18:43:53.492160653 +0200 -@@ -259,10 +259,14 @@ - - CAVEATS - -- Groupnames must start with a lower case letter or an underscore, -- followed by lower case letters, digits, underscores, or dashes. -- They can end with a dollar sign. -- In regular expression terms: [a-z_][a-z0-9_-]*[$]? -+ Groupnames may contain only lower and upper case letters, digits, -+ underscores, or dashes. They can end with a dollar sign. -+ -+ Dashes are not allowed at the beginning of the groupname. -+ Fully numeric groupnames and groupnames . or .. are -+ also disallowed. -+ -+ In regular expression terms: [a-zA-Z0-9_.][a-zA-Z0-9_.-]*[$]? - - - Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long. -diff -up shadow-4.1.5.1/man/useradd.8.xml.goodname shadow-4.1.5.1/man/useradd.8.xml ---- shadow-4.1.5.1/man/useradd.8.xml.goodname 2012-05-25 13:45:29.000000000 +0200 -+++ shadow-4.1.5.1/man/useradd.8.xml 2012-09-19 18:43:53.493160675 +0200 -@@ -366,7 +366,7 @@ - - - -- Do no create the user's home directory, even if the system -+ Do not create the user's home directory, even if the system - wide setting from /etc/login.defs - () is set to - yes. -@@ -654,10 +654,16 @@ - - - -- Usernames must start with a lower case letter or an underscore, -- followed by lower case letters, digits, underscores, or dashes. -- They can end with a dollar sign. -- In regular expression terms: [a-z_][a-z0-9_-]*[$]? -+ Usernames may contain only lower and upper case letters, digits, -+ underscores, or dashes. They can end with a dollar sign. -+ -+ Dashes are not allowed at the beginning of the username. -+ Fully numeric usernames and usernames . or .. are -+ also disallowed. It is not recommended to use usernames beginning -+ with . character as their home directories will be hidden in -+ the ls output. -+ -+ In regular expression terms: [a-zA-Z0-9_.][a-zA-Z0-9_.-]*[$]? - - - Usernames may only be up to 32 characters long. diff --git a/SOURCES/shadow-4.1.5.1-id-alloc.patch b/SOURCES/shadow-4.1.5.1-id-alloc.patch deleted file mode 100644 index 6c55739..0000000 --- a/SOURCES/shadow-4.1.5.1-id-alloc.patch +++ /dev/null @@ -1,1213 +0,0 @@ -Previously, this allocation was optimized for an outdated -deployment style (that of /etc/group alongside nss_db). The issue -here is that this results in extremely poor performance when using -SSSD, Winbind or nss_ldap. - -There were actually two serious bugs here that have been addressed: - -1) Running getgrent() loops won't work in most SSSD or Winbind -environments, as full group enumeration is disabled by default. -This could easily result in auto-allocating a group that was -already in use. (This might result in a security issue as well, if -the shared GID is a privileged group). - -2) For system groups, the loop was always iterating through the -complete SYS_GID_MIN->SYS_GID_MAX range. On SSSD and Winbind, this -means hundreds of round-trips to LDAP (unless the GIDs were -specifically configured to be ignored by the SSSD or winbindd). -To a user with a slow connection to their LDAP server, this would -appear as if groupadd -r was hung. (Though it would eventually -complete). - -This patch changes the algorithm to be more favorable for LDAP -environments, at the expense of some performance when using nss_db. -Given that the DB is a local service, this should have a negligible -effect from a user's perspective. - -With the new algorithm, we simply first iterate through all entries -in the local database with gr_next(), recording the IDs that are in -use. We then start from the highest presumed-available entry and -call getgrgid() to see if it is available. We continue this until -we come to the first unused GID. We then select that and return it. - -If we make it through all the remaining IDs without finding a free -one, we start over from the beginning of the range and try to find -room in one of the gaps in the range. - -The patch was originally written by Stephen Gallagher and applied -identically also to the user allocation by Tomáš Mráz. - -diff -up shadow-4.1.5.1/libmisc/find_new_gid.c.id-alloc shadow-4.1.5.1/libmisc/find_new_gid.c ---- shadow-4.1.5.1/libmisc/find_new_gid.c.id-alloc 2014-09-10 10:25:41.165524986 +0200 -+++ shadow-4.1.5.1/libmisc/find_new_gid.c 2014-09-10 10:25:41.195525677 +0200 -@@ -39,6 +39,118 @@ - #include "getdef.h" - - /* -+ * get_ranges - Get the minimum and maximum ID ranges for the search -+ * -+ * This function will return the minimum and maximum ranges for IDs -+ * -+ * 0: The function completed successfully -+ * EINVAL: The provided ranges are impossible (such as maximum < minimum) -+ * -+ * preferred_min: The special-case minimum value for a specifically- -+ * requested ID, which may be lower than the standard min_id -+ */ -+static int get_ranges(bool sys_group, gid_t *min_id, gid_t *max_id, -+ gid_t *preferred_min) -+{ -+ gid_t gid_def_max = 0; -+ -+ if (sys_group) { -+ /* System groups */ -+ -+ /* A requested ID is allowed to be below the autoselect range */ -+ *preferred_min = (gid_t) 1; -+ -+ /* Get the minimum ID range from login.defs or default to 101 */ -+ *min_id = (gid_t) getdef_ulong("SYS_GID_MIN", 101UL); -+ -+ /* -+ * If SYS_GID_MAX is unspecified, we should assume it to be one -+ * less than the GID_MIN (which is reserved for non-system accounts) -+ */ -+ gid_def_max = (gid_t) getdef_ulong("GID_MIN", 1000UL) - 1; -+ *max_id = (gid_t) getdef_ulong("SYS_GID_MAX", -+ (unsigned long) gid_def_max); -+ -+ /* Check that the ranges make sense */ -+ if (*max_id < *min_id) { -+ (void) fprintf (stderr, -+ _("%s: Invalid configuration: SYS_GID_MIN (%lu), " -+ "GID_MIN (%lu), SYS_GID_MAX (%lu)\n"), -+ Prog, (unsigned long) *min_id, -+ getdef_ulong ("GID_MIN", 1000UL), -+ (unsigned long) *max_id); -+ return EINVAL; -+ } -+ } else { -+ /* Non-system groups */ -+ -+ /* Get the values from login.defs or use reasonable defaults */ -+ *min_id = (gid_t) getdef_ulong("GID_MIN", 1000UL); -+ *max_id = (gid_t) getdef_ulong("GID_MAX", 60000UL); -+ -+ /* -+ * The preferred minimum should match the standard ID minimum -+ * for non-system groups. -+ */ -+ *preferred_min = *min_id; -+ -+ /* Check that the ranges make sense */ -+ if (*max_id < *min_id) { -+ (void) fprintf(stderr, -+ _("%s: Invalid configuration: GID_MIN (%lu), " -+ "GID_MAX (%lu)\n"), -+ Prog, (unsigned long) *min_id, -+ (unsigned long) *max_id); -+ return EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * check_gid - See if the requested GID is available -+ * -+ * On success, return 0 -+ * If the ID is in use, return EEXIST -+ * If the ID is outside the range, return ERANGE -+ * In other cases, return errno from getgrgid() -+ */ -+static int check_gid(const gid_t gid, -+ const gid_t gid_min, -+ const gid_t gid_max, -+ bool *used_gids) -+{ -+ /* First test that the preferred ID is in the range */ -+ if (gid < gid_min || gid > gid_max) { -+ return ERANGE; -+ } -+ -+ /* -+ * Check whether we already detected this GID -+ * using the gr_next() loop -+ */ -+ if (used_gids != NULL && used_gids[gid]) { -+ return EEXIST; -+ } -+ /* Check if the GID exists according to NSS */ -+ errno = 0; -+ if (getgrgid(gid) != NULL) { -+ return EEXIST; -+ } else { -+ /* getgrgid() was NULL, check whether this was -+ * due to an error, so we can report it. -+ */ -+ /* ignore errors for now * if (errno != 0) { -+ return errno; -+ } */ -+ } -+ -+ /* If we've made it here, the GID must be available */ -+ return 0; -+} -+ -+/* - * find_new_gid - Find a new unused GID. - * - * If successful, find_new_gid provides an unused group ID in the -@@ -48,166 +160,339 @@ - * - * Return 0 on success, -1 if no unused GIDs are available. - */ --int find_new_gid (bool sys_group, -- gid_t *gid, -- /*@null@*/gid_t const *preferred_gid) -+int find_new_gid(bool sys_group, -+ gid_t *gid, -+ /*@null@*/gid_t const *preferred_gid) - { -- const struct group *grp; -- gid_t gid_min, gid_max, group_id; - bool *used_gids; -+ const struct group *grp; -+ gid_t gid_min, gid_max, preferred_min; -+ gid_t group_id, id; -+ gid_t lowest_found, highest_found; -+ int result; -+ int nospam = 0; - -- assert (gid != NULL); -+ assert(gid != NULL); - -- if (!sys_group) { -- gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL); -- gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL); -- if (gid_max < gid_min) { -- (void) fprintf (stderr, -- _("%s: Invalid configuration: GID_MIN (%lu), GID_MAX (%lu)\n"), -- Prog, (unsigned long) gid_min, (unsigned long) gid_max); -- return -1; -- } -- } else { -- gid_min = (gid_t) 1; -- gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1; -- gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max); -- if (gid_max < gid_min) { -- (void) fprintf (stderr, -- _("%s: Invalid configuration: SYS_GID_MIN (%lu), GID_MIN (%lu), SYS_GID_MAX (%lu)\n"), -- Prog, (unsigned long) gid_min, getdef_ulong ("GID_MIN", 1000UL), (unsigned long) gid_max); -+ /* -+ * First, figure out what ID range is appropriate for -+ * automatic assignment -+ */ -+ result = get_ranges(sys_group, &gid_min, &gid_max, &preferred_min); -+ if (result == EINVAL) { -+ return -1; -+ } -+ -+ /* Check if the preferred GID is available */ -+ if (preferred_gid) { -+ result = check_gid(*preferred_gid, preferred_min, gid_max, NULL); -+ if (result == 0) { -+ /* -+ * Make sure the GID isn't queued for use already -+ */ -+ if (gr_locate_gid (*preferred_gid) == NULL) { -+ *gid = *preferred_gid; -+ return 0; -+ } -+ /* -+ * gr_locate_gid() found the GID in an as-yet uncommitted -+ * entry. We'll proceed below and auto-set a GID. -+ */ -+ } else if (result == EEXIST || result == ERANGE) { -+ /* -+ * Continue on below. At this time, we won't -+ * treat these two cases differently. -+ */ -+ } else { -+ /* -+ * An unexpected error occurred. We should report -+ * this and fail the group creation. -+ * This differs from the automatic creation -+ * behavior below, since if a specific GID was -+ * requested and generated an error, the user is -+ * more likely to want to stop and address the -+ * issue. -+ */ -+ fprintf(stderr, -+ _("%s: Encountered error attempting to use " -+ "preferred GID: %s\n"), -+ Prog, strerror(result)); - return -1; - } - } -+ -+ /* -+ * Search the entire group file, -+ * looking for the next unused value. -+ * -+ * We first check the local database with gr_rewind/gr_next to find -+ * all local values that are in use. -+ * -+ * We then compare the next free value to all databases (local and -+ * remote) and iterate until we find a free one. If there are free -+ * values beyond the lowest (system groups) or highest (non-system -+ * groups), we will prefer those and avoid potentially reclaiming a -+ * deleted group (which can be a security issue, since it may grant -+ * access to files belonging to that former group). -+ * -+ * If there are no GIDs available at the end of the search, we will -+ * have no choice but to iterate through the range looking for gaps. -+ * -+ */ -+ -+ /* Create an array to hold all of the discovered GIDs */ - used_gids = malloc (sizeof (bool) * (gid_max +1)); - if (NULL == used_gids) { - fprintf (stderr, -- _("%s: failed to allocate memory: %s\n"), -- Prog, strerror (errno)); -+ _("%s: failed to allocate memory: %s\n"), -+ Prog, strerror (errno)); - return -1; - } - memset (used_gids, false, sizeof (bool) * (gid_max + 1)); - -- if ( (NULL != preferred_gid) -- && (*preferred_gid >= gid_min) -- && (*preferred_gid <= gid_max) -- /* Check if the user exists according to NSS */ -- && (getgrgid (*preferred_gid) == NULL) -- /* Check also the local database in case of uncommitted -- * changes */ -- && (gr_locate_gid (*preferred_gid) == NULL)) { -- *gid = *preferred_gid; -- free (used_gids); -- return 0; -- } -- -- /* if we did not find free preffered system gid, we start to look for -- * one in the range assigned to dynamic system IDs */ -- if (sys_group) -- gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); -+ /* First look for the lowest and highest value in the local database */ -+ (void) gr_rewind (); -+ highest_found = gid_min; -+ lowest_found = gid_max; -+ while ((grp = gr_next ()) != NULL) { -+ /* -+ * Does this entry have a lower GID than the lowest we've found -+ * so far? -+ */ -+ if ((grp->gr_gid <= lowest_found) && (grp->gr_gid >= gid_min)) { -+ lowest_found = grp->gr_gid - 1; -+ } -+ -+ /* -+ * Does this entry have a higher GID than the highest we've found -+ * so far? -+ */ -+ if ((grp->gr_gid >= highest_found) && (grp->gr_gid <= gid_max)) { -+ highest_found = grp->gr_gid + 1; -+ } -+ -+ /* create index of used GIDs */ -+ if (grp->gr_gid >= gid_min -+ && grp->gr_gid <= gid_max) { -+ -+ used_gids[grp->gr_gid] = true; -+ } -+ } - -- /* -- * Search the entire group file, -- * looking for the largest unused value. -- * -- * We check the list of groups according to NSS (setgrent/getgrent), -- * but we also check the local database (gr_rewind/gr_next) in case -- * some groups were created but the changes were not committed yet. -- */ - if (sys_group) { -- gid_t id; -- /* setgrent / getgrent / endgrent can be very slow with -- * LDAP configurations (and many accounts). -- * Since there is a limited amount of IDs to be tested -- * for system accounts, we just check the existence -- * of IDs with getgrgid. -- */ -- group_id = gid_max; -- for (id = gid_max; id >= gid_min; id--) { -- if (getgrgid (id) != NULL) { -- group_id = id - 1; -- used_gids[id] = true; -- } -+ /* -+ * For system groups, we want to start from the -+ * top of the range and work downwards. -+ */ -+ -+ /* -+ * At the conclusion of the gr_next() search, we will either -+ * have a presumed-free GID or we will be at GID_MIN - 1. -+ */ -+ if (lowest_found < gid_min) { -+ /* -+ * In this case, a GID is in use at GID_MIN. -+ * -+ * We will reset the search to GID_MAX and proceed down -+ * through all the GIDs (skipping those we detected with -+ * used_gids) for a free one. It is a known issue that -+ * this may result in reusing a previously-deleted GID, -+ * so administrators should be instructed to use this -+ * auto-detection with care (and prefer to assign GIDs -+ * explicitly). -+ */ -+ lowest_found = gid_max; - } - -- (void) gr_rewind (); -- while ((grp = gr_next ()) != NULL) { -- if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) { -- group_id = grp->gr_gid - 1; -- } -- /* create index of used GIDs */ -- if (grp->gr_gid <= gid_max) { -- used_gids[grp->gr_gid] = true; -+ /* Search through all of the IDs in the range */ -+ for (id = lowest_found; id >= gid_min; id--) { -+ result = check_gid(id, gid_min, gid_max, used_gids); -+ if (result == 0) { -+ /* This GID is available. Return it. */ -+ *gid = id; -+ free(used_gids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This GID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique system GID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available GIDs: %s", -+ strerror(result))); -+ nospam = 1; -+ } -+ /* -+ * We will continue anyway. Hopefully a later GID -+ * will work properly. -+ */ - } - } -- } else { -- group_id = gid_min; -- setgrent (); -- while ((grp = getgrent ()) != NULL) { -- if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) { -- group_id = grp->gr_gid + 1; -- } -- /* create index of used GIDs */ -- if (grp->gr_gid <= gid_max) { -- used_gids[grp->gr_gid] = true; -+ -+ /* -+ * If we get all the way through the loop, try again from GID_MAX, -+ * unless that was where we previously started. (NOTE: the worst-case -+ * scenario here is that we will run through (GID_MAX - GID_MIN - 1) -+ * cycles *again* if we fall into this case with lowest_found as -+ * GID_MAX - 1, all groups in the range in use and maintained by -+ * network services such as LDAP.) -+ */ -+ if (lowest_found != gid_max) { -+ for (id = gid_max; id >= gid_min; id--) { -+ result = check_gid(id, gid_min, gid_max, used_gids); -+ if (result == 0) { -+ /* This GID is available. Return it. */ -+ *gid = id; -+ free(used_gids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This GID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique system GID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available GIDs: %s", -+ strerror(result))); -+ nospam = 1; -+ } -+ /* -+ * We will continue anyway. Hopefully a later GID -+ * will work properly. -+ */ -+ } - } - } -- endgrent (); -+ } else { /* !sys_group */ -+ /* -+ * For non-system groups, we want to start from the -+ * bottom of the range and work upwards. -+ */ - -- (void) gr_rewind (); -- while ((grp = gr_next ()) != NULL) { -- if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) { -- group_id = grp->gr_gid + 1; -- } -- /* create index of used GIDs */ -- if (grp->gr_gid <= gid_max) { -- used_gids[grp->gr_gid] = true; -- } -+ /* -+ * At the conclusion of the gr_next() search, we will either -+ * have a presumed-free GID or we will be at GID_MAX + 1. -+ */ -+ if (highest_found > gid_max) { -+ /* -+ * In this case, a GID is in use at GID_MAX. -+ * -+ * We will reset the search to GID_MIN and proceed up -+ * through all the GIDs (skipping those we detected with -+ * used_gids) for a free one. It is a known issue that -+ * this may result in reusing a previously-deleted GID, -+ * so administrators should be instructed to use this -+ * auto-detection with care (and prefer to assign GIDs -+ * explicitly). -+ */ -+ highest_found = gid_min; - } -- } - -- /* -- * If a group (resp. system group) with GID equal to GID_MAX (resp. -- * GID_MIN) exists, the above algorithm will give us GID_MAX+1 -- * (resp. GID_MIN-1) even if not unique. Search for the first free -- * GID starting with GID_MIN (resp. GID_MAX). -- */ -- if (sys_group) { -- if (group_id < gid_min) { -- for (group_id = gid_max; group_id >= gid_min; group_id--) { -- if (false == used_gids[group_id]) { -- break; -+ /* Search through all of the IDs in the range */ -+ for (id = highest_found; id <= gid_max; id++) { -+ result = check_gid(id, gid_min, gid_max, used_gids); -+ if (result == 0) { -+ /* This GID is available. Return it. */ -+ *gid = id; -+ free(used_gids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This GID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique GID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available GIDs: %s", -+ strerror(result))); -+ nospam = 1; - } -- } -- if (group_id < gid_min) { -- fprintf (stderr, -- _("%s: Can't get unique system GID (no more available GIDs)\n"), -- Prog); -- SYSLOG ((LOG_WARN, -- "no more available GID on the system")); -- free (used_gids); -- return -1; -+ /* -+ * We will continue anyway. Hopefully a later GID -+ * will work properly. -+ */ - } - } -- } else { -- if (group_id > gid_max) { -- for (group_id = gid_min; group_id <= gid_max; group_id++) { -- if (false == used_gids[group_id]) { -- break; -+ -+ /* -+ * If we get all the way through the loop, try again from GID_MIN, -+ * unless that was where we previously started. (NOTE: the worst-case -+ * scenario here is that we will run through (GID_MAX - GID_MIN - 1) -+ * cycles *again* if we fall into this case with highest_found as -+ * GID_MIN + 1, all groups in the range in use and maintained by -+ * network services such as LDAP.) -+ */ -+ if (highest_found != gid_min) { -+ for (id = gid_min; id <= gid_max; id++) { -+ result = check_gid(id, gid_min, gid_max, used_gids); -+ if (result == 0) { -+ /* This GID is available. Return it. */ -+ *gid = id; -+ free(used_gids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This GID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique GID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available GIDs: %s", -+ strerror(result))); -+ nospam = 1; -+ } -+ /* -+ * We will continue anyway. Hopefully a later GID -+ * will work properly. -+ */ - } - } -- if (group_id > gid_max) { -- fprintf (stderr, -- _("%s: Can't get unique GID (no more available GIDs)\n"), -- Prog); -- SYSLOG ((LOG_WARN, "no more available GID on the system")); -- free (used_gids); -- return -1; -- } - } - } - -- free (used_gids); -- *gid = group_id; -- return 0; -+ /* The code reached here and found no available IDs in the range */ -+ fprintf(stderr, -+ _("%s: Can't get unique GID (no more available GIDs)\n"), -+ Prog); -+ SYSLOG((LOG_WARN, "no more available GIDs on the system")); -+ free(used_gids); -+ return -1; - } - -diff -up shadow-4.1.5.1/libmisc/find_new_uid.c.id-alloc shadow-4.1.5.1/libmisc/find_new_uid.c ---- shadow-4.1.5.1/libmisc/find_new_uid.c.id-alloc 2011-07-29 17:39:16.000000000 +0200 -+++ shadow-4.1.5.1/libmisc/find_new_uid.c 2014-10-17 16:52:30.481217270 +0200 -@@ -39,6 +39,118 @@ - #include "getdef.h" - - /* -+ * get_ranges - Get the minimum and maximum ID ranges for the search -+ * -+ * This function will return the minimum and maximum ranges for IDs -+ * -+ * 0: The function completed successfully -+ * EINVAL: The provided ranges are impossible (such as maximum < minimum) -+ * -+ * preferred_min: The special-case minimum value for a specifically- -+ * requested ID, which may be lower than the standard min_id -+ */ -+static int get_ranges(bool sys_user, uid_t *min_id, uid_t *max_id, -+ uid_t *preferred_min) -+{ -+ uid_t uid_def_max = 0; -+ -+ if (sys_user) { -+ /* System users */ -+ -+ /* A requested ID is allowed to be below the autoselect range */ -+ *preferred_min = (uid_t) 1; -+ -+ /* Get the minimum ID range from login.defs or default to 101 */ -+ *min_id = (uid_t) getdef_ulong("SYS_UID_MIN", 101UL); -+ -+ /* -+ * If SYS_UID_MAX is unspecified, we should assume it to be one -+ * less than the UID_MIN (which is reserved for non-system accounts) -+ */ -+ uid_def_max = (uid_t) getdef_ulong("UID_MIN", 1000UL) - 1; -+ *max_id = (uid_t) getdef_ulong("SYS_UID_MAX", -+ (unsigned long) uid_def_max); -+ -+ /* Check that the ranges make sense */ -+ if (*max_id < *min_id) { -+ (void) fprintf (stderr, -+ _("%s: Invalid configuration: SYS_UID_MIN (%lu), " -+ "UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), -+ Prog, (unsigned long) *min_id, -+ getdef_ulong ("UID_MIN", 1000UL), -+ (unsigned long) *max_id); -+ return EINVAL; -+ } -+ } else { -+ /* Non-system users */ -+ -+ /* Get the values from login.defs or use reasonable defaults */ -+ *min_id = (uid_t) getdef_ulong("UID_MIN", 1000UL); -+ *max_id = (uid_t) getdef_ulong("UID_MAX", 60000UL); -+ -+ /* -+ * The preferred minimum should match the standard ID minimum -+ * for non-system users. -+ */ -+ *preferred_min = *min_id; -+ -+ /* Check that the ranges make sense */ -+ if (*max_id < *min_id) { -+ (void) fprintf(stderr, -+ _("%s: Invalid configuration: UID_MIN (%lu), " -+ "UID_MAX (%lu)\n"), -+ Prog, (unsigned long) *min_id, -+ (unsigned long) *max_id); -+ return EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * check_uid - See if the requested UID is available -+ * -+ * On success, return 0 -+ * If the ID is in use, return EEXIST -+ * If the ID is outside the range, return ERANGE -+ * In other cases, return errno from getpwuid() -+ */ -+static int check_uid(const uid_t uid, -+ const uid_t uid_min, -+ const uid_t uid_max, -+ bool *used_uids) -+{ -+ /* First test that the preferred ID is in the range */ -+ if (uid < uid_min || uid > uid_max) { -+ return ERANGE; -+ } -+ -+ /* -+ * Check whether we already detected this UID -+ * using the pw_next() loop -+ */ -+ if (used_uids != NULL && used_uids[uid]) { -+ return EEXIST; -+ } -+ /* Check if the UID exists according to NSS */ -+ errno = 0; -+ if (getpwuid(uid) != NULL) { -+ return EEXIST; -+ } else { -+ /* getpwuid() was NULL, check whether this was -+ * due to an error, so we can report it. -+ */ -+ /* ignore errors for now * if (errno != 0) { -+ return errno; -+ } */ -+ } -+ -+ /* If we've made it here, the UID must be available */ -+ return 0; -+} -+ -+/* - * find_new_uid - Find a new unused UID. - * - * If successful, find_new_uid provides an unused user ID in the -@@ -48,162 +160,339 @@ - * - * Return 0 on success, -1 if no unused UIDs are available. - */ --int find_new_uid (bool sys_user, -- uid_t *uid, -- /*@null@*/uid_t const *preferred_uid) -+int find_new_uid(bool sys_user, -+ uid_t *uid, -+ /*@null@*/uid_t const *preferred_uid) - { -- const struct passwd *pwd; -- uid_t uid_min, uid_max, user_id; - bool *used_uids; -+ const struct passwd *pwd; -+ uid_t uid_min, uid_max, preferred_min; -+ uid_t user_id, id; -+ uid_t lowest_found, highest_found; -+ int result; -+ int nospam = 0; - - assert (uid != NULL); - -- if (!sys_user) { -- uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); -- uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); -- if (uid_max < uid_min) { -- (void) fprintf (stderr, -- _("%s: Invalid configuration: UID_MIN (%lu), UID_MAX (%lu)\n"), -- Prog, (unsigned long) uid_min, (unsigned long) uid_max); -- return -1; -- } -- } else { -- uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL); -- uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1; -- uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); -- if (uid_max < uid_min) { -- (void) fprintf (stderr, -- _("%s: Invalid configuration: SYS_UID_MIN (%lu), UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), -- Prog, (unsigned long) uid_min, getdef_ulong ("UID_MIN", 1000UL), (unsigned long) uid_max); -+ /* -+ * First, figure out what ID range is appropriate for -+ * automatic assignment -+ */ -+ result = get_ranges(sys_user, &uid_min, &uid_max, &preferred_min); -+ if (result == EINVAL) { -+ return -1; -+ } -+ -+ /* Check if the preferred UID is available */ -+ if (preferred_uid) { -+ result = check_uid(*preferred_uid, preferred_min, uid_max, NULL); -+ if (result == 0) { -+ /* -+ * Make sure the UID isn't queued for use already -+ */ -+ if (pw_locate_uid (*preferred_uid) == NULL) { -+ *uid = *preferred_uid; -+ return 0; -+ } -+ /* -+ * pw_locate_uid() found the UID in an as-yet uncommitted -+ * entry. We'll proceed below and auto-set an UID. -+ */ -+ } else if (result == EEXIST || result == ERANGE) { -+ /* -+ * Continue on below. At this time, we won't -+ * treat these two cases differently. -+ */ -+ } else { -+ /* -+ * An unexpected error occurred. We should report -+ * this and fail the user creation. -+ * This differs from the automatic creation -+ * behavior below, since if a specific UID was -+ * requested and generated an error, the user is -+ * more likely to want to stop and address the -+ * issue. -+ */ -+ fprintf(stderr, -+ _("%s: Encountered error attempting to use " -+ "preferred UID: %s\n"), -+ Prog, strerror(result)); - return -1; - } - } -+ -+ /* -+ * Search the entire passwd file, -+ * looking for the next unused value. -+ * -+ * We first check the local database with pw_rewind/pw_next to find -+ * all local values that are in use. -+ * -+ * We then compare the next free value to all databases (local and -+ * remote) and iterate until we find a free one. If there are free -+ * values beyond the lowest (system users) or highest (non-system -+ * users), we will prefer those and avoid potentially reclaiming a -+ * deleted user (which can be a security issue, since it may grant -+ * access to files belonging to that former user). -+ * -+ * If there are no UIDs available at the end of the search, we will -+ * have no choice but to iterate through the range looking for gaps. -+ * -+ */ -+ -+ /* Create an array to hold all of the discovered UIDs */ - used_uids = malloc (sizeof (bool) * (uid_max +1)); - if (NULL == used_uids) { - fprintf (stderr, -- _("%s: failed to allocate memory: %s\n"), -- Prog, strerror (errno)); -+ _("%s: failed to allocate memory: %s\n"), -+ Prog, strerror (errno)); - return -1; - } - memset (used_uids, false, sizeof (bool) * (uid_max + 1)); - -- if ( (NULL != preferred_uid) -- && (*preferred_uid >= uid_min) -- && (*preferred_uid <= uid_max) -- /* Check if the user exists according to NSS */ -- && (getpwuid (*preferred_uid) == NULL) -- /* Check also the local database in case of uncommitted -- * changes */ -- && (pw_locate_uid (*preferred_uid) == NULL)) { -- *uid = *preferred_uid; -- free (used_uids); -- return 0; -- } -+ /* First look for the lowest and highest value in the local database */ -+ (void) pw_rewind (); -+ highest_found = uid_min; -+ lowest_found = uid_max; -+ while ((pwd = pw_next ()) != NULL) { -+ /* -+ * Does this entry have a lower UID than the lowest we've found -+ * so far? -+ */ -+ if ((pwd->pw_uid <= lowest_found) && (pwd->pw_uid >= uid_min)) { -+ lowest_found = pwd->pw_uid - 1; -+ } - -+ /* -+ * Does this entry have a higher UID than the highest we've found -+ * so far? -+ */ -+ if ((pwd->pw_uid >= highest_found) && (pwd->pw_uid <= uid_max)) { -+ highest_found = pwd->pw_uid + 1; -+ } -+ -+ /* create index of used UIDs */ -+ if (pwd->pw_uid >= uid_min -+ && pwd->pw_uid <= uid_max) { -+ -+ used_uids[pwd->pw_uid] = true; -+ } -+ } - -- /* -- * Search the entire password file, -- * looking for the largest unused value. -- * -- * We check the list of users according to NSS (setpwent/getpwent), -- * but we also check the local database (pw_rewind/pw_next) in case -- * some users were created but the changes were not committed yet. -- */ - if (sys_user) { -- uid_t id; -- /* setpwent / getpwent / endpwent can be very slow with -- * LDAP configurations (and many accounts). -- * Since there is a limited amount of IDs to be tested -- * for system accounts, we just check the existence -- * of IDs with getpwuid. -- */ -- user_id = uid_max; -- for (id = uid_max; id >= uid_min; id--) { -- if (getpwuid (id) != NULL) { -- user_id = id - 1; -- used_uids[id] = true; -- } -+ /* -+ * For system users, we want to start from the -+ * top of the range and work downwards. -+ */ -+ -+ /* -+ * At the conclusion of the pw_next() search, we will either -+ * have a presumed-free UID or we will be at UID_MIN - 1. -+ */ -+ if (lowest_found < uid_min) { -+ /* -+ * In this case, an UID is in use at UID_MIN. -+ * -+ * We will reset the search to UID_MAX and proceed down -+ * through all the UIDs (skipping those we detected with -+ * used_uids) for a free one. It is a known issue that -+ * this may result in reusing a previously-deleted UID, -+ * so administrators should be instructed to use this -+ * auto-detection with care (and prefer to assign UIDs -+ * explicitly). -+ */ -+ lowest_found = uid_max; - } - -- (void) pw_rewind (); -- while ((pwd = pw_next ()) != NULL) { -- if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) { -- user_id = pwd->pw_uid - 1; -- } -- /* create index of used UIDs */ -- if (pwd->pw_uid <= uid_max) { -- used_uids[pwd->pw_uid] = true; -+ /* Search through all of the IDs in the range */ -+ for (id = lowest_found; id >= uid_min; id--) { -+ result = check_uid(id, uid_min, uid_max, used_uids); -+ if (result == 0) { -+ /* This UID is available. Return it. */ -+ *uid = id; -+ free(used_uids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This UID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique system UID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available UIDs: %s", -+ strerror(result))); -+ nospam = 1; -+ } -+ /* -+ * We will continue anyway. Hopefully a later UID -+ * will work properly. -+ */ - } - } -- } else { -- user_id = uid_min; -- setpwent (); -- while ((pwd = getpwent ()) != NULL) { -- if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { -- user_id = pwd->pw_uid + 1; -- } -- /* create index of used UIDs */ -- if (pwd->pw_uid <= uid_max) { -- used_uids[pwd->pw_uid] = true; -+ -+ /* -+ * If we get all the way through the loop, try again from UID_MAX, -+ * unless that was where we previously started. (NOTE: the worst-case -+ * scenario here is that we will run through (UID_MAX - UID_MIN - 1) -+ * cycles *again* if we fall into this case with lowest_found as -+ * UID_MAX - 1, all users in the range in use and maintained by -+ * network services such as LDAP.) -+ */ -+ if (lowest_found != uid_max) { -+ for (id = uid_max; id >= uid_min; id--) { -+ result = check_uid(id, uid_min, uid_max, used_uids); -+ if (result == 0) { -+ /* This UID is available. Return it. */ -+ *uid = id; -+ free(used_uids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This UID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique system UID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available UIDs: %s", -+ strerror(result))); -+ nospam = 1; -+ } -+ /* -+ * We will continue anyway. Hopefully a later UID -+ * will work properly. -+ */ -+ } - } - } -- endpwent (); -+ } else { /* !sys_user */ -+ /* -+ * For non-system users, we want to start from the -+ * bottom of the range and work upwards. -+ */ - -- (void) pw_rewind (); -- while ((pwd = pw_next ()) != NULL) { -- if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { -- user_id = pwd->pw_uid + 1; -- } -- /* create index of used UIDs */ -- if (pwd->pw_uid <= uid_max) { -- used_uids[pwd->pw_uid] = true; -- } -+ /* -+ * At the conclusion of the pw_next() search, we will either -+ * have a presumed-free UID or we will be at UID_MAX + 1. -+ */ -+ if (highest_found > uid_max) { -+ /* -+ * In this case, a UID is in use at UID_MAX. -+ * -+ * We will reset the search to UID_MIN and proceed up -+ * through all the UIDs (skipping those we detected with -+ * used_uids) for a free one. It is a known issue that -+ * this may result in reusing a previously-deleted UID, -+ * so administrators should be instructed to use this -+ * auto-detection with care (and prefer to assign UIDs -+ * explicitly). -+ */ -+ highest_found = uid_min; - } -- } - -- /* -- * If a user (resp. system user) with UID equal to UID_MAX (resp. -- * UID_MIN) exists, the above algorithm will give us UID_MAX+1 -- * (resp. UID_MIN-1) even if not unique. Search for the first free -- * UID starting with UID_MIN (resp. UID_MAX). -- */ -- if (sys_user) { -- if (user_id < uid_min) { -- for (user_id = uid_max; user_id >= uid_min; user_id--) { -- if (false == used_uids[user_id]) { -- break; -+ /* Search through all of the IDs in the range */ -+ for (id = highest_found; id <= uid_max; id++) { -+ result = check_uid(id, uid_min, uid_max, used_uids); -+ if (result == 0) { -+ /* This UID is available. Return it. */ -+ *uid = id; -+ free(used_uids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This UID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique UID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available UIDs: %s", -+ strerror(result))); -+ nospam = 1; - } -- } -- if (user_id < uid_min ) { -- fprintf (stderr, -- _("%s: Can't get unique system UID (no more available UIDs)\n"), -- Prog); -- SYSLOG ((LOG_WARN, -- "no more available UID on the system")); -- free (used_uids); -- return -1; -+ /* -+ * We will continue anyway. Hopefully a later UID -+ * will work properly. -+ */ - } - } -- } else { -- if (user_id > uid_max) { -- for (user_id = uid_min; user_id <= uid_max; user_id++) { -- if (false == used_uids[user_id]) { -- break; -+ -+ /* -+ * If we get all the way through the loop, try again from UID_MIN, -+ * unless that was where we previously started. (NOTE: the worst-case -+ * scenario here is that we will run through (UID_MAX - UID_MIN - 1) -+ * cycles *again* if we fall into this case with highest_found as -+ * UID_MIN + 1, all users in the range in use and maintained by -+ * network services such as LDAP.) -+ */ -+ if (highest_found != uid_min) { -+ for (id = uid_min; id <= uid_max; id++) { -+ result = check_uid(id, uid_min, uid_max, used_uids); -+ if (result == 0) { -+ /* This UID is available. Return it. */ -+ *uid = id; -+ free(used_uids); -+ return 0; -+ } else if (result == EEXIST) { -+ /* This UID is in use, we'll continue to the next */ -+ } else { -+ /* -+ * An unexpected error occurred. -+ * -+ * Only report it the first time to avoid spamming -+ * the logs -+ * -+ */ -+ if (!nospam) { -+ fprintf(stderr, -+ _("%s: Can't get unique UID (%s). " -+ "Suppressing additional messages.\n"), -+ Prog, strerror(result)); -+ SYSLOG((LOG_ERR, -+ "Error checking available UIDs: %s", -+ strerror(result))); -+ nospam = 1; -+ } -+ /* -+ * We will continue anyway. Hopefully a later UID -+ * will work properly. -+ */ - } - } -- if (user_id > uid_max) { -- fprintf (stderr, -- _("%s: Can't get unique UID (no more available UIDs)\n"), -- Prog); -- SYSLOG ((LOG_WARN, "no more available UID on the system")); -- free (used_uids); -- return -1; -- } - } - } - -- free (used_uids); -- *uid = user_id; -- return 0; -+ /* The code reached here and found no available IDs in the range */ -+ fprintf(stderr, -+ _("%s: Can't get unique UID (no more available UIDs)\n"), -+ Prog); -+ SYSLOG((LOG_WARN, "no more available UIDs on the system")); -+ free(used_uids); -+ return -1; - } - diff --git a/SOURCES/shadow-4.1.5.1-info-parent-dir.patch b/SOURCES/shadow-4.1.5.1-info-parent-dir.patch index b05e5bb..b3a525b 100644 --- a/SOURCES/shadow-4.1.5.1-info-parent-dir.patch +++ b/SOURCES/shadow-4.1.5.1-info-parent-dir.patch @@ -1,7 +1,8 @@ -diff -up shadow-4.1.5.1/man/newusers.8.xml.info-parent-dir shadow-4.1.5.1/man/newusers.8.xml ---- shadow-4.1.5.1/man/newusers.8.xml.info-parent-dir 2012-05-25 13:45:28.000000000 +0200 -+++ shadow-4.1.5.1/man/newusers.8.xml 2012-09-19 18:46:35.651613365 +0200 -@@ -216,7 +216,15 @@ +Index: shadow-4.5/man/newusers.8.xml +=================================================================== +--- shadow-4.5.orig/man/newusers.8.xml ++++ shadow-4.5/man/newusers.8.xml +@@ -218,7 +218,15 @@ If this field does not specify an existing directory, the specified directory is created, with ownership set to the diff --git a/SOURCES/shadow-4.1.5.1-ingroup.patch b/SOURCES/shadow-4.1.5.1-ingroup.patch deleted file mode 100644 index 1844fbc..0000000 --- a/SOURCES/shadow-4.1.5.1-ingroup.patch +++ /dev/null @@ -1,121 +0,0 @@ -diff -up shadow-4.1.5.1/src/newgrp.c.ingroup shadow-4.1.5.1/src/newgrp.c ---- shadow-4.1.5.1/src/newgrp.c.ingroup 2018-04-24 16:55:24.546677529 +0200 -+++ shadow-4.1.5.1/src/newgrp.c 2018-04-24 16:58:17.113445562 +0200 -@@ -83,15 +83,29 @@ static void usage (void) - } - } - -+static bool ingroup(const char *name, struct group *gr) -+{ -+ char **look; -+ bool notfound = true; -+ -+ look = gr->gr_mem; -+ while (*look && notfound) -+ notfound = strcmp (*look++, name); -+ -+ return !notfound; -+} -+ - /* -- * find_matching_group - search all groups of a given group id for -+ * find_matching_group - search all groups of a gr's group id for - * membership of a given username -+ * but check gr itself first - */ --static /*@null@*/struct group *find_matching_group (const char *name, gid_t gid) -+static /*@null@*/struct group *find_matching_group (const char *name, struct group *gr) - { -- struct group *gr; -- char **look; -- bool notfound = true; -+ gid_t gid = gr->gr_gid; -+ -+ if (ingroup(name, gr)) -+ return gr; - - setgrent (); - while ((gr = getgrent ()) != NULL) { -@@ -103,14 +117,8 @@ static /*@null@*/struct group *find_matc - * A group with matching GID was found. - * Test for membership of 'name'. - */ -- look = gr->gr_mem; -- while ((NULL != *look) && notfound) { -- notfound = (strcmp (*look, name) != 0); -- look++; -- } -- if (!notfound) { -+ if (ingroup(name, gr)) - break; -- } - } - endgrent (); - return gr; -@@ -373,6 +381,7 @@ int main (int argc, char **argv) - { - bool initflag = false; - int i; -+ bool is_member = false; - bool cflag = false; - int err = 0; - gid_t gid; -@@ -611,22 +620,36 @@ int main (int argc, char **argv) - goto failure; - } - -+#ifdef HAVE_SETGROUPS -+ /* when using pam_group, she will not be listed in the groups -+ * database. However getgroups() will return the group. So -+ * if she is listed there already it is ok to grant membership. -+ */ -+ for (i = 0; i < ngroups; i++) { -+ if (grp->gr_gid == grouplist[i]) { -+ is_member = true; -+ break; -+ } -+ } -+#endif /* HAVE_SETGROUPS */ - /* - * For splitted groups (due to limitations of NIS), check all - * groups of the same GID like the requested group for - * membership of the current user. - */ -- grp = find_matching_group (name, grp->gr_gid); -- if (NULL == grp) { -- /* -- * No matching group found. As we already know that -- * the group exists, this happens only in the case -- * of a requested group where the user is not member. -- * -- * Re-read the group entry for further processing. -- */ -- grp = xgetgrnam (group); -- assert (NULL != grp); -+ if (!is_member) { -+ grp = find_matching_group (name, grp); -+ if (NULL == grp) { -+ /* -+ * No matching group found. As we already know that -+ * the group exists, this happens only in the case -+ * of a requested group where the user is not member. -+ * -+ * Re-read the group entry for further processing. -+ */ -+ grp = xgetgrnam (group); -+ assert (NULL != grp); -+ } - } - #ifdef SHADOWGRP - sgrp = getsgnam (group); -@@ -639,7 +662,9 @@ int main (int argc, char **argv) - /* - * Check if the user is allowed to access this group. - */ -- check_perms (grp, pwd, group); -+ if (!is_member) { -+ check_perms (grp, pwd, group); -+ } - - /* - * all successful validations pass through this point. The group id diff --git a/SOURCES/shadow-4.1.5.1-ja-translation.patch b/SOURCES/shadow-4.1.5.1-ja-translation.patch deleted file mode 100644 index 407cc3f..0000000 --- a/SOURCES/shadow-4.1.5.1-ja-translation.patch +++ /dev/null @@ -1,25 +0,0 @@ -From f2ce4cc54edc7dfeb6b12f3e8fff98255a9f477d Mon Sep 17 00:00:00 2001 -From: Taizo Ito -Date: Tue, 17 Mar 2015 13:51:27 +0900 -Subject: [PATCH 1/1] typo in japanese man page of useradd - ---- - po/ja.po | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/po/ja.po b/po/ja.po -index a68a698..0c21c29 100644 ---- a/po/ja.po -+++ b/po/ja.po -@@ -2047,7 +2047,7 @@ msgid " -s, --shell SHELL login shell of the new account\n" - msgstr " -s, --shell SHELL 新アカウントのログインシェル\n" - - msgid " -u, --uid UID user ID of the new account\n" --msgstr " -u, --iud UID 新アカウントのユーザ ID\n" -+msgstr " -u, --uid UID 新アカウントのユーザ ID\n" - - msgid "" - " -U, --user-group create a group with the same name as the " --- -1.8.3.1 - diff --git a/SOURCES/shadow-4.1.5.1-lastlog-unexpire.patch b/SOURCES/shadow-4.1.5.1-lastlog-unexpire.patch deleted file mode 100644 index 6a7ae2a..0000000 --- a/SOURCES/shadow-4.1.5.1-lastlog-unexpire.patch +++ /dev/null @@ -1,263 +0,0 @@ -diff -up shadow-4.1.5.1/man/lastlog.8.xml.unexpire shadow-4.1.5.1/man/lastlog.8.xml ---- shadow-4.1.5.1/man/lastlog.8.xml.unexpire 2012-05-25 13:45:28.000000000 +0200 -+++ shadow-4.1.5.1/man/lastlog.8.xml 2016-04-28 15:09:11.026084219 +0200 -@@ -105,6 +105,17 @@ - - - -+ , -+ -+ -+ -+ Clear lastlog record of an user. This option can be used only together -+ with ()). -+ -+ -+ -+ -+ - , - - -@@ -124,6 +135,17 @@ - - - -+ -+ -+ , -+ -+ -+ -+ Set lastlog record of an user to the current time. This option can be -+ used only together with ()). -+ -+ -+ - - - , -diff -up shadow-4.1.5.1/src/lastlog.c.unexpire shadow-4.1.5.1/src/lastlog.c ---- shadow-4.1.5.1/src/lastlog.c.unexpire 2011-11-06 21:54:18.000000000 +0100 -+++ shadow-4.1.5.1/src/lastlog.c 2016-04-28 15:49:30.253371990 +0200 -@@ -55,6 +55,13 @@ - #endif - - /* -+ * Needed for systems with older audit library. -+ */ -+#ifndef AUDIT_ACCT_UNLOCK -+#define AUDIT_ACCT_UNLOCK 1136 -+#endif -+ -+/* - * Global variables - */ - const char *Prog; /* Program name */ -@@ -71,6 +78,8 @@ static struct stat statbuf; /* fstat buf - static bool uflg = false; /* print only an user of range of users */ - static bool tflg = false; /* print is restricted to most recent days */ - static bool bflg = false; /* print excludes most recent days */ -+static bool Cflg = false; /* clear record for user */ -+static bool Sflg = false; /* set record for user */ - - #define NOW (time ((time_t *) 0)) - -@@ -83,8 +92,10 @@ static /*@noreturn@*/void usage (int sta - "Options:\n"), - Prog); - (void) fputs (_(" -b, --before DAYS print only lastlog records older than DAYS\n"), usageout); -+ (void) fputs (_(" -C, --clear clear lastlog record of an user (usable only with -u)\n"), usageout); - (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); - (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); -+ (void) fputs (_(" -S, --set set lastlog record to current time (usable only with -u)\n"), usageout); - (void) fputs (_(" -t, --time DAYS print only lastlog records more recent than DAYS\n"), usageout); - (void) fputs (_(" -u, --user LOGIN print lastlog record of the specified LOGIN\n"), usageout); - (void) fputs ("\n", usageout); -@@ -194,6 +205,80 @@ static void print (void) - } - } - -+static void update_one (/*@null@*/const struct passwd *pw) -+{ -+ off_t offset; -+ struct lastlog ll; -+ int err; -+ -+ if (NULL == pw) { -+ return; -+ } -+ -+ offset = (off_t) pw->pw_uid * sizeof (ll); -+ /* fseeko errors are not really relevant for us. */ -+ err = fseeko (lastlogfile, offset, SEEK_SET); -+ assert (0 == err); -+ -+ memzero (&ll, sizeof (ll)); -+ -+ if (Sflg) { -+ ll.ll_time = NOW; -+#ifdef HAVE_LL_HOST -+ strcpy (ll.ll_host, "localhost"); -+#endif -+ strcpy (ll.ll_line, "lastlog"); -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_ACCT_UNLOCK, Prog, -+ "clearing-lastlog", -+ pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS); -+#endif -+ } -+#ifdef WITH_AUDIT -+ else { -+ audit_logger (AUDIT_ACCT_UNLOCK, Prog, -+ "refreshing-lastlog", -+ pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS); -+ } -+#endif -+ -+ if (fwrite (&ll, sizeof(ll), 1, lastlogfile) != 1) { -+ fprintf (stderr, -+ _("%s: Failed to update the entry for UID %lu\n"), -+ Prog, (unsigned long int)pw->pw_uid); -+ exit (EXIT_FAILURE); -+ } -+} -+ -+static void update (void) -+{ -+ const struct passwd *pwent; -+ -+ if (!uflg) /* safety measure */ -+ return; -+ -+ if (has_umin && has_umax && (umin == umax)) { -+ update_one (getpwuid ((uid_t)umin)); -+ } else { -+ setpwent (); -+ while ( (pwent = getpwent ()) != NULL ) { -+ if ((has_umin && (pwent->pw_uid < (uid_t)umin)) -+ || (has_umax && (pwent->pw_uid > (uid_t)umax))) { -+ continue; -+ } -+ update_one (pwent); -+ } -+ endpwent (); -+ } -+ -+ if (fflush (lastlogfile) != 0 || fsync (fileno (lastlogfile)) != 0) { -+ fprintf (stderr, -+ _("%s: Failed to update the lastlog file\n"), -+ Prog); -+ exit (EXIT_FAILURE); -+ } -+} -+ - int main (int argc, char **argv) - { - /* -@@ -208,18 +293,24 @@ int main (int argc, char **argv) - - process_root_flag ("-R", argc, argv); - -+#ifdef WITH_AUDIT -+ audit_help_open (); -+#endif -+ - { - int c; - static struct option const longopts[] = { - {"before", required_argument, NULL, 'b'}, -+ {"clear", no_argument, NULL, 'C'}, - {"help", no_argument, NULL, 'h'}, - {"root", required_argument, NULL, 'R'}, -+ {"set", no_argument, NULL, 'S'}, - {"time", required_argument, NULL, 't'}, - {"user", required_argument, NULL, 'u'}, - {NULL, 0, NULL, '\0'} - }; - -- while ((c = getopt_long (argc, argv, "b:hR:t:u:", longopts, -+ while ((c = getopt_long (argc, argv, "b:ChR:St:u:", longopts, - NULL)) != -1) { - switch (c) { - case 'b': -@@ -235,11 +326,21 @@ int main (int argc, char **argv) - bflg = true; - break; - } -+ case 'C': -+ { -+ Cflg = true; -+ break; -+ } - case 'h': - usage (EXIT_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ - break; -+ case 'S': -+ { -+ Sflg = true; -+ break; -+ } - case 't': - { - unsigned long days; -@@ -294,9 +395,21 @@ int main (int argc, char **argv) - Prog, argv[optind]); - usage (EXIT_FAILURE); - } -+ if (Cflg && Sflg) { -+ fprintf (stderr, -+ _("%s: Option -C cannot be used together with option -S\n"), -+ Prog); -+ usage (EXIT_FAILURE); -+ } -+ if ((Cflg || Sflg) && !uflg) { -+ fprintf (stderr, -+ _("%s: Options -C and -S require option -u to specify the user\n"), -+ Prog); -+ usage (EXIT_FAILURE); -+ } - } - -- lastlogfile = fopen (LASTLOG_FILE, "r"); -+ lastlogfile = fopen (LASTLOG_FILE, (Cflg || Sflg)?"r+":"r"); - if (NULL == lastlogfile) { - perror (LASTLOG_FILE); - exit (EXIT_FAILURE); -@@ -310,7 +423,10 @@ int main (int argc, char **argv) - exit (EXIT_FAILURE); - } - -- print (); -+ if (Cflg || Sflg) -+ update (); -+ else -+ print (); - - (void) fclose (lastlogfile); - -diff -up shadow-4.1.5.1/src/Makefile.am.unexpire shadow-4.1.5.1/src/Makefile.am ---- shadow-4.1.5.1/src/Makefile.am.unexpire 2011-11-18 22:23:30.000000000 +0100 -+++ shadow-4.1.5.1/src/Makefile.am 2016-04-28 15:09:11.027084241 +0200 -@@ -90,6 +90,7 @@ groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) - grpck_LDADD = $(LDADD) $(LIBSELINUX) - grpconv_LDADD = $(LDADD) $(LIBSELINUX) - grpunconv_LDADD = $(LDADD) $(LIBSELINUX) -+lastlog_LDADD = $(LDADD) $(LIBAUDIT) - login_SOURCES = \ - login.c \ - login_nopam.c -diff -up shadow-4.1.5.1/src/Makefile.in.unexpire shadow-4.1.5.1/src/Makefile.in ---- shadow-4.1.5.1/src/Makefile.in.unexpire 2012-05-25 13:56:51.000000000 +0200 -+++ shadow-4.1.5.1/src/Makefile.in 2016-04-28 15:09:11.027084241 +0200 -@@ -162,7 +162,7 @@ id_DEPENDENCIES = $(am__DEPENDENCIES_1) - $(top_builddir)/lib/libshadow.la - lastlog_SOURCES = lastlog.c - lastlog_OBJECTS = lastlog.$(OBJEXT) --lastlog_LDADD = $(LDADD) -+lastlog_LDADD = $(LDADD) $(LIBAUDIT) - lastlog_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(top_builddir)/libmisc/libmisc.a \ - $(top_builddir)/lib/libshadow.la diff --git a/SOURCES/shadow-4.1.5.1-logmsg.patch b/SOURCES/shadow-4.1.5.1-logmsg.patch index 7d5cbc8..ca7e57b 100644 --- a/SOURCES/shadow-4.1.5.1-logmsg.patch +++ b/SOURCES/shadow-4.1.5.1-logmsg.patch @@ -1,7 +1,8 @@ -diff -up shadow-4.1.5.1/src/useradd.c.logmsg shadow-4.1.5.1/src/useradd.c ---- shadow-4.1.5.1/src/useradd.c.logmsg 2013-02-20 15:41:44.000000000 +0100 -+++ shadow-4.1.5.1/src/useradd.c 2013-03-19 18:40:04.908292810 +0100 -@@ -275,7 +275,7 @@ static void fail_exit (int code) +Index: shadow-4.5/src/useradd.c +=================================================================== +--- shadow-4.5.orig/src/useradd.c ++++ shadow-4.5/src/useradd.c +@@ -323,7 +323,7 @@ static void fail_exit (int code) user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif diff --git a/SOURCES/shadow-4.1.5.1-long-entry.patch b/SOURCES/shadow-4.1.5.1-long-entry.patch deleted file mode 100644 index eaf9689..0000000 --- a/SOURCES/shadow-4.1.5.1-long-entry.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff -up shadow-4.1.5.1/lib/defines.h.long-entry shadow-4.1.5.1/lib/defines.h ---- shadow-4.1.5.1/lib/defines.h.long-entry 2011-09-18 22:44:10.000000000 +0200 -+++ shadow-4.1.5.1/lib/defines.h 2018-04-24 16:34:31.261417493 +0200 -@@ -382,4 +382,7 @@ extern char *strerror (); - # endif - #endif - -+/* Maximum length of passwd entry */ -+#define PASSWD_ENTRY_MAX_LENGTH 32768 -+ - #endif /* _DEFINES_H_ */ -diff -up shadow-4.1.5.1/lib/pwio.c.long-entry shadow-4.1.5.1/lib/pwio.c ---- shadow-4.1.5.1/lib/pwio.c.long-entry 2011-02-16 21:32:24.000000000 +0100 -+++ shadow-4.1.5.1/lib/pwio.c 2018-04-24 16:34:31.263417454 +0200 -@@ -79,7 +79,10 @@ static int passwd_put (const void *ent, - || (pw->pw_gid == (gid_t)-1) - || (valid_field (pw->pw_gecos, ":\n") == -1) - || (valid_field (pw->pw_dir, ":\n") == -1) -- || (valid_field (pw->pw_shell, ":\n") == -1)) { -+ || (valid_field (pw->pw_shell, ":\n") == -1) -+ || (strlen (pw->pw_name) + strlen (pw->pw_passwd) + -+ strlen (pw->pw_gecos) + strlen (pw->pw_dir) + -+ strlen (pw->pw_shell) + 100 > PASSWD_ENTRY_MAX_LENGTH)) { - return -1; - } - -diff -up shadow-4.1.5.1/lib/sgetpwent.c.long-entry shadow-4.1.5.1/lib/sgetpwent.c ---- shadow-4.1.5.1/lib/sgetpwent.c.long-entry 2009-04-06 06:28:53.000000000 +0200 -+++ shadow-4.1.5.1/lib/sgetpwent.c 2018-04-24 16:34:31.263417454 +0200 -@@ -57,7 +57,7 @@ - struct passwd *sgetpwent (const char *buf) - { - static struct passwd pwent; -- static char pwdbuf[1024]; -+ static char pwdbuf[PASSWD_ENTRY_MAX_LENGTH]; - register int i; - register char *cp; - char *fields[NFIELDS]; -@@ -67,8 +67,10 @@ struct passwd *sgetpwent (const char *bu - * the password structure remain valid. - */ - -- if (strlen (buf) >= sizeof pwdbuf) -+ if (strlen (buf) >= sizeof pwdbuf) { -+ fprintf (stderr, "Too long passwd entry encountered, file corruption?\n"); - return 0; /* fail if too long */ -+ } - strcpy (pwdbuf, buf); - - /* -diff -up shadow-4.1.5.1/lib/sgetspent.c.long-entry shadow-4.1.5.1/lib/sgetspent.c ---- shadow-4.1.5.1/lib/sgetspent.c.long-entry 2009-04-12 04:46:43.000000000 +0200 -+++ shadow-4.1.5.1/lib/sgetspent.c 2018-04-24 16:34:31.264417435 +0200 -@@ -48,7 +48,7 @@ - */ - struct spwd *sgetspent (const char *string) - { -- static char spwbuf[1024]; -+ static char spwbuf[PASSWD_ENTRY_MAX_LENGTH]; - static struct spwd spwd; - char *fields[FIELDS]; - char *cp; -@@ -61,6 +61,7 @@ struct spwd *sgetspent (const char *stri - */ - - if (strlen (string) >= sizeof spwbuf) { -+ fprintf (stderr, "Too long shadow entry encountered, file corruption?\n"); - return 0; /* fail if too long */ - } - strcpy (spwbuf, string); -diff -up shadow-4.1.5.1/lib/shadowio.c.long-entry shadow-4.1.5.1/lib/shadowio.c ---- shadow-4.1.5.1/lib/shadowio.c.long-entry 2011-02-16 21:32:24.000000000 +0100 -+++ shadow-4.1.5.1/lib/shadowio.c 2018-04-24 16:34:31.265417416 +0200 -@@ -78,7 +78,9 @@ static int shadow_put (const void *ent, - - if ( (NULL == sp) - || (valid_field (sp->sp_namp, ":\n") == -1) -- || (valid_field (sp->sp_pwdp, ":\n") == -1)) { -+ || (valid_field (sp->sp_pwdp, ":\n") == -1) -+ || (strlen (sp->sp_namp) + strlen (sp->sp_pwdp) + -+ 1000 > PASSWD_ENTRY_MAX_LENGTH)) { - return -1; - } - diff --git a/SOURCES/shadow-4.1.5.1-manfix.patch b/SOURCES/shadow-4.1.5.1-manfix.patch deleted file mode 100644 index 18dc342..0000000 --- a/SOURCES/shadow-4.1.5.1-manfix.patch +++ /dev/null @@ -1,281 +0,0 @@ -diff -up shadow-4.1.5.1/man/chage.1.xml.manfix shadow-4.1.5.1/man/chage.1.xml ---- shadow-4.1.5.1/man/chage.1.xml.manfix 2012-05-25 13:45:27.000000000 +0200 -+++ shadow-4.1.5.1/man/chage.1.xml 2018-04-24 16:43:48.545743715 +0200 -@@ -102,6 +102,9 @@ - Set the number of days since January 1st, 1970 when the password - was last changed. The date may also be expressed in the format - YYYY-MM-DD (or the format more commonly used in your area). -+ If the LAST_DAY is set to -+ 0 the user is forced to change his password -+ on the next log on. - - - -@@ -123,6 +126,13 @@ - EXPIRE_DATE will remove an account - expiration date. - -+ -+ For example the following command can be used -+ to set an account to expire in 180 days: -+ -+ -+ chage -E $(date -d +180days +%Y-%m-%d) -+ - - - -diff -up shadow-4.1.5.1/man/groupmems.8.xml.manfix shadow-4.1.5.1/man/groupmems.8.xml ---- shadow-4.1.5.1/man/groupmems.8.xml.manfix 2012-05-25 13:45:28.000000000 +0200 -+++ shadow-4.1.5.1/man/groupmems.8.xml 2015-12-18 12:27:08.466909647 +0100 -@@ -194,6 +194,13 @@ - $ chown root.groups groupmems - $ groupmems -g groups -a gk4 - -+ -+ -+ In the Red Hat Enterprise Linux 7 the groupmems -+ command is not setuid and regular users cannot use it to manipulate -+ the membership of their own group. This might change in future -+ major releases of the Red Hat Enterprise Linux. -+ - - - -diff -up shadow-4.1.5.1/man/ja/man5/login.defs.5.manfix shadow-4.1.5.1/man/ja/man5/login.defs.5 ---- shadow-4.1.5.1/man/ja/man5/login.defs.5.manfix 2012-05-25 13:45:27.000000000 +0200 -+++ shadow-4.1.5.1/man/ja/man5/login.defs.5 2015-12-18 12:34:08.080715842 +0100 -@@ -147,10 +147,6 @@ 以下の参照表は、 - shadow パスワード機能のどのプログラムが - どのパラメータを使用するかを示したものである。 - .na --.IP chfn 12 --CHFN_AUTH CHFN_RESTRICT --.IP chsh 12 --CHFN_AUTH - .IP groupadd 12 - GID_MAX GID_MIN - .IP newusers 12 -diff -up shadow-4.1.5.1/man/login.defs.5.xml.manfix shadow-4.1.5.1/man/login.defs.5.xml ---- shadow-4.1.5.1/man/login.defs.5.xml.manfix 2012-05-25 13:45:28.000000000 +0200 -+++ shadow-4.1.5.1/man/login.defs.5.xml 2014-08-29 13:31:38.364812323 +0200 -@@ -160,6 +160,17 @@ - long numeric parameters is machine-dependent. - - -+ -+ Please note that the parameters in this configuration file control the -+ behavior of the tools from the shadow-utils component. None of these -+ tools uses the PAM mechanism, and the utilities that use PAM (such as the -+ passwd command) should be configured elsewhere. The only values that -+ affect PAM modules are ENCRYPT_METHOD and SHA_CRYPT_MAX_ROUNDS -+ for pam_unix module, FAIL_DELAY for pam_faildelay module, -+ and UMASK for pam_umask module. Refer to -+ pam(8) for more information. -+ -+ - The following configuration items are provided: - - -@@ -248,26 +258,6 @@ - - - -- chfn -- -- -- CHFN_AUTH -- CHFN_RESTRICT -- LOGIN_STRING -- -- -- -- -- chgpasswd -- -- -- ENCRYPT_METHOD MAX_MEMBERS_PER_GROUP MD5_CRYPT_ENAB -- SHA_CRYPT_MAX_ROUNDS -- SHA_CRYPT_MIN_ROUNDS -- -- -- -- - chpasswd - - -@@ -278,14 +268,6 @@ - - - -- -- chsh -- -- -- CHSH_AUTH LOGIN_STRING -- -- -- - - - -@@ -346,34 +328,6 @@ - - - -- -- login -- -- -- CONSOLE -- CONSOLE_GROUPS DEFAULT_HOME -- ENV_HZ ENV_PATH ENV_SUPATH -- ENV_TZ ENVIRON_FILE -- ERASECHAR FAIL_DELAY -- FAILLOG_ENAB -- FAKE_SHELL -- FTMP_FILE -- HUSHLOGIN_FILE -- ISSUE_FILE -- KILLCHAR -- LASTLOG_ENAB -- LOGIN_RETRIES -- LOGIN_STRING -- LOGIN_TIMEOUT LOG_OK_LOGINS LOG_UNKFAIL_ENAB -- MAIL_CHECK_ENAB MAIL_DIR MAIL_FILE -- MOTD_FILE NOLOGINS_FILE PORTTIME_CHECKS_ENAB -- QUOTAS_ENAB -- TTYGROUP TTYPERM TTYTYPE_FILE -- ULIMIT UMASK -- USERGROUPS_ENAB -- -- -- - - - newgrp / sg -@@ -399,17 +353,6 @@ - - - -- -- passwd -- -- -- ENCRYPT_METHOD MD5_CRYPT_ENAB OBSCURE_CHECKS_ENAB -- PASS_ALWAYS_WARN PASS_CHANGE_TRIES PASS_MAX_LEN PASS_MIN_LEN -- SHA_CRYPT_MAX_ROUNDS -- SHA_CRYPT_MIN_ROUNDS -- -- -- - - pwck - -@@ -436,32 +379,6 @@ - - - -- -- su -- -- -- CONSOLE -- CONSOLE_GROUPS DEFAULT_HOME -- ENV_HZ ENVIRON_FILE -- ENV_PATH ENV_SUPATH -- ENV_TZ LOGIN_STRING MAIL_CHECK_ENAB -- MAIL_DIR MAIL_FILE QUOTAS_ENAB -- SULOG_FILE SU_NAME -- SU_WHEEL_ONLY -- SYSLOG_SU_ENAB -- USERGROUPS_ENAB -- -- -- -- -- sulogin -- -- -- ENV_HZ -- ENV_TZ -- -- -- - - useradd - -diff -up shadow-4.1.5.1/man/useradd.8.xml.manfix shadow-4.1.5.1/man/useradd.8.xml ---- shadow-4.1.5.1/man/useradd.8.xml.manfix 2015-12-17 14:05:47.930742412 +0100 -+++ shadow-4.1.5.1/man/useradd.8.xml 2015-12-17 14:05:47.945742754 +0100 -@@ -134,8 +134,8 @@ - HOME_DIR is not specified. - BASE_DIR is - concatenated with the account name to define the home directory. -- If the option is not used, -- BASE_DIR must exist. -+ The BASE_DIR must exist otherwise -+ the home directory cannot be created. - - - If this option is not specified, useradd -@@ -161,7 +161,7 @@ - - - -- , -+ , - HOME_DIR - - -@@ -171,8 +171,7 @@ - login directory. The default is to append the - LOGIN name to - BASE_DIR and use that as the login -- directory name. The directory HOME_DIR -- does not have to exist but will not be created if it is missing. -+ directory name. - - - -@@ -358,11 +357,16 @@ - is not enabled, no home - directories are created. - -+ -+ The directory where the user's home directory is created must -+ exist and have proper SELinux context and permissions. Otherwise -+ the user's home directory cannot be created or accessed. -+ - - - - -- -+ , - - - -diff -up shadow-4.1.5.1/man/usermod.8.xml.manfix shadow-4.1.5.1/man/usermod.8.xml ---- shadow-4.1.5.1/man/usermod.8.xml.manfix 2012-05-25 13:45:29.000000000 +0200 -+++ shadow-4.1.5.1/man/usermod.8.xml 2014-08-29 13:33:40.814632618 +0200 -@@ -132,7 +132,8 @@ - If the - option is given, the contents of the current home directory will - be moved to the new home directory, which is created if it does -- not already exist. -+ not already exist. If the current home directory does not exist -+ the new home directory will not be created. - - - -@@ -261,7 +262,8 @@ - - - Move the content of the user's home directory to the new -- location. -+ location. If the current home directory does not exist -+ the new home directory will not be created. - - - This option is only valid in combination with the diff --git a/SOURCES/shadow-4.1.5.1-merge-group.patch b/SOURCES/shadow-4.1.5.1-merge-group.patch deleted file mode 100644 index f5cea10..0000000 --- a/SOURCES/shadow-4.1.5.1-merge-group.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff -up shadow-4.1.5.1/lib/groupio.c.merge-group shadow-4.1.5.1/lib/groupio.c ---- shadow-4.1.5.1/lib/groupio.c.merge-group 2011-02-16 21:32:24.000000000 +0100 -+++ shadow-4.1.5.1/lib/groupio.c 2013-01-29 13:56:43.049275513 +0100 -@@ -330,12 +330,12 @@ static /*@null@*/struct commonio_entry * - - /* Concatenate the 2 lines */ - new_line_len = strlen (gr1->line) + strlen (gr2->line) +1; -- new_line = (char *)malloc ((new_line_len + 1) * sizeof(char*)); -+ new_line = (char *)malloc (new_line_len + 1); - if (NULL == new_line) { - errno = ENOMEM; - return NULL; - } -- snprintf(new_line, new_line_len, "%s\n%s", gr1->line, gr2->line); -+ snprintf(new_line, new_line_len + 1, "%s\n%s", gr1->line, gr2->line); - new_line[new_line_len] = '\0'; - - /* Concatenate the 2 list of members */ -@@ -353,7 +353,7 @@ static /*@null@*/struct commonio_entry * - members++; - } - } -- new_members = (char **)malloc ( (members+1) * sizeof(char*) ); -+ new_members = (char **)calloc (members+1, sizeof(char*)); - if (NULL == new_members) { - free (new_line); - errno = ENOMEM; diff --git a/SOURCES/shadow-4.1.5.1-move-home.patch b/SOURCES/shadow-4.1.5.1-move-home.patch deleted file mode 100644 index c87e232..0000000 --- a/SOURCES/shadow-4.1.5.1-move-home.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff -up shadow-4.1.5.1/src/usermod.c.move-home shadow-4.1.5.1/src/usermod.c ---- shadow-4.1.5.1/src/usermod.c.move-home 2014-08-29 13:31:38.000000000 +0200 -+++ shadow-4.1.5.1/src/usermod.c 2014-08-29 14:14:13.860671177 +0200 -@@ -1571,6 +1571,11 @@ static void move_home (void) - Prog, user_home, user_newhome); - fail_exit (E_HOMEDIR); - } -+ } else { -+ fprintf (stderr, -+ _("%s: The previous home directory (%s) does " -+ "not exist or is inaccessible. Move cannot be completed.\n"), -+ Prog, user_home); - } - } - diff --git a/SOURCES/shadow-4.1.5.1-null-tm.patch b/SOURCES/shadow-4.1.5.1-null-tm.patch deleted file mode 100644 index e531d14..0000000 --- a/SOURCES/shadow-4.1.5.1-null-tm.patch +++ /dev/null @@ -1,86 +0,0 @@ -diff -up shadow-4.1.5.1/src/faillog.c.null-tm shadow-4.1.5.1/src/faillog.c ---- shadow-4.1.5.1/src/faillog.c.null-tm 2011-11-19 23:54:47.000000000 +0100 -+++ shadow-4.1.5.1/src/faillog.c 2016-06-14 11:54:58.582314219 +0200 -@@ -163,10 +163,14 @@ static void print_one (/*@null@*/const s - } - - tm = localtime (&fl.fail_time); -+ if (tm == NULL) { -+ cp = "(unknown)"; -+ } else { - #ifdef HAVE_STRFTIME -- strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm); -- cp = ptime; -+ strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm); -+ cp = ptime; - #endif -+ } - printf ("%-9s %5d %5d ", - pw->pw_name, fl.fail_cnt, fl.fail_max); - /* FIXME: cp is not defined ifndef HAVE_STRFTIME */ -diff -up shadow-4.1.5.1/src/chage.c.null-tm shadow-4.1.5.1/src/chage.c ---- shadow-4.1.5.1/src/chage.c.null-tm 2016-05-04 13:44:55.639787900 +0200 -+++ shadow-4.1.5.1/src/chage.c 2016-06-14 11:54:58.583314243 +0200 -@@ -168,6 +168,10 @@ static void date_to_str (char *buf, size - struct tm *tp; - - tp = gmtime (&date); -+ if (tp == NULL) { -+ (void) snprintf (buf, maxsize, "(unknown)"); -+ return; -+ } - #ifdef HAVE_STRFTIME - (void) strftime (buf, maxsize, "%Y-%m-%d", tp); - #else -diff -up shadow-4.1.5.1/src/lastlog.c.null-tm shadow-4.1.5.1/src/lastlog.c ---- shadow-4.1.5.1/src/lastlog.c.null-tm 2016-05-04 13:44:55.647788082 +0200 -+++ shadow-4.1.5.1/src/lastlog.c 2016-06-14 11:54:58.584314267 +0200 -@@ -165,13 +165,17 @@ static void print_one (/*@null@*/const s - - ll_time = ll.ll_time; - tm = localtime (&ll_time); -+ if (tm == NULL) { -+ cp = "(unknown)"; -+ } else { - #ifdef HAVE_STRFTIME -- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); -- cp = ptime; -+ strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); -+ cp = ptime; - #else -- cp = asctime (tm); -- cp[24] = '\0'; -+ cp = asctime (tm); -+ cp[24] = '\0'; - #endif -+ } - - if (ll.ll_time == (time_t) 0) { - cp = _("**Never logged in**\0"); -diff -up shadow-4.1.5.1/src/passwd.c.null-tm shadow-4.1.5.1/src/passwd.c ---- shadow-4.1.5.1/src/passwd.c.null-tm 2016-05-04 13:44:55.634787787 +0200 -+++ shadow-4.1.5.1/src/passwd.c 2016-06-14 11:54:58.584314267 +0200 -@@ -438,6 +438,9 @@ static /*@observer@*/const char *date_to - struct tm *tm; - - tm = gmtime (&t); -+ if (tm == NULL) { -+ return "(unknown)"; -+ } - #ifdef HAVE_STRFTIME - (void) strftime (buf, sizeof buf, "%m/%d/%Y", tm); - #else /* !HAVE_STRFTIME */ -diff -up shadow-4.1.5.1/src/usermod.c.null-tm shadow-4.1.5.1/src/usermod.c ---- shadow-4.1.5.1/src/usermod.c.null-tm 2016-05-04 13:44:55.648788104 +0200 -+++ shadow-4.1.5.1/src/usermod.c 2016-06-14 11:54:58.585314291 +0200 -@@ -186,6 +186,10 @@ static void date_to_str (/*@unique@*//*@ - } else { - time_t t = (time_t) date; - tp = gmtime (&t); -+ if (tp == NULL) { -+ strncpy (buf, "unknown", maxsize); -+ return; -+ } - #ifdef HAVE_STRFTIME - strftime (buf, maxsize, "%Y-%m-%d", tp); - #else diff --git a/SOURCES/shadow-4.1.5.1-orig-context.patch b/SOURCES/shadow-4.1.5.1-orig-context.patch deleted file mode 100644 index c1ddb13..0000000 --- a/SOURCES/shadow-4.1.5.1-orig-context.patch +++ /dev/null @@ -1,128 +0,0 @@ -diff -up shadow-4.1.5.1/lib/commonio.c.orig-context shadow-4.1.5.1/lib/commonio.c ---- shadow-4.1.5.1/lib/commonio.c.orig-context 2012-09-19 20:27:16.000000000 +0200 -+++ shadow-4.1.5.1/lib/commonio.c 2013-02-20 15:20:55.064962324 +0100 -@@ -941,7 +941,7 @@ int commonio_close (struct commonio_db * - snprintf (buf, sizeof buf, "%s-", db->filename); - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (buf) != 0) { -+ if (set_selinux_file_context (buf, db->filename) != 0) { - errors++; - } - #endif -@@ -975,7 +975,7 @@ int commonio_close (struct commonio_db * - snprintf (buf, sizeof buf, "%s+", db->filename); - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (buf) != 0) { -+ if (set_selinux_file_context (buf, db->filename) != 0) { - errors++; - } - #endif -diff -up shadow-4.1.5.1/libmisc/copydir.c.orig-context shadow-4.1.5.1/libmisc/copydir.c ---- shadow-4.1.5.1/libmisc/copydir.c.orig-context 2012-02-13 20:16:32.000000000 +0100 -+++ shadow-4.1.5.1/libmisc/copydir.c 2013-02-20 15:19:01.495623232 +0100 -@@ -484,7 +484,7 @@ static int copy_dir (const char *src, co - */ - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - return -1; - } - #endif /* WITH_SELINUX */ -@@ -605,7 +605,7 @@ static int copy_symlink (const char *src - } - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - free (oldlink); - return -1; - } -@@ -684,7 +684,7 @@ static int copy_special (const char *src - int err = 0; - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - return -1; - } - #endif /* WITH_SELINUX */ -@@ -744,7 +744,7 @@ static int copy_file (const char *src, c - return -1; - } - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - return -1; - } - #endif /* WITH_SELINUX */ -diff -up shadow-4.1.5.1/lib/prototypes.h.orig-context shadow-4.1.5.1/lib/prototypes.h ---- shadow-4.1.5.1/lib/prototypes.h.orig-context 2012-01-08 17:04:29.000000000 +0100 -+++ shadow-4.1.5.1/lib/prototypes.h 2013-02-20 15:24:17.251126575 +0100 -@@ -295,7 +295,7 @@ extern /*@observer@*/const char *crypt_m - - /* selinux.c */ - #ifdef WITH_SELINUX --extern int set_selinux_file_context (const char *dst_name); -+extern int set_selinux_file_context (const char *dst_name, const char *orig_name); - extern int reset_selinux_file_context (void); - #endif - -diff -up shadow-4.1.5.1/lib/selinux.c.orig-context shadow-4.1.5.1/lib/selinux.c ---- shadow-4.1.5.1/lib/selinux.c.orig-context 2012-01-08 17:35:44.000000000 +0100 -+++ shadow-4.1.5.1/lib/selinux.c 2013-02-20 15:16:40.383716877 +0100 -@@ -50,7 +50,7 @@ static bool selinux_enabled; - * Callers may have to Reset SELinux to create files with default - * contexts with reset_selinux_file_context - */ --int set_selinux_file_context (const char *dst_name) -+int set_selinux_file_context (const char *dst_name, const char *orig_name) - { - /*@null@*/security_context_t scontext = NULL; - -@@ -62,19 +62,23 @@ int set_selinux_file_context (const char - if (selinux_enabled) { - /* Get the default security context for this file */ - if (matchpathcon (dst_name, 0, &scontext) < 0) { -- if (security_getenforce () != 0) { -- return 1; -- } -+ /* We could not get the default, copy the original */ -+ if (orig_name == NULL) -+ goto error; -+ if (getfilecon (orig_name, &scontext) < 0) -+ goto error; - } - /* Set the security context for the next created file */ -- if (setfscreatecon (scontext) < 0) { -- if (security_getenforce () != 0) { -- return 1; -- } -- } -+ if (setfscreatecon (scontext) < 0) -+ goto error; - freecon (scontext); - } - return 0; -+ error: -+ if (security_getenforce () != 0) { -+ return 1; -+ } -+ return 0; - } - - /* -diff -up shadow-4.1.5.1/src/useradd.c.orig-context shadow-4.1.5.1/src/useradd.c ---- shadow-4.1.5.1/src/useradd.c.orig-context 2012-09-19 20:23:33.000000000 +0200 -+++ shadow-4.1.5.1/src/useradd.c 2013-02-20 15:19:31.221235459 +0100 -@@ -1759,7 +1759,7 @@ static void create_home (void) - { - if (access (user_home, F_OK) != 0) { - #ifdef WITH_SELINUX -- if (set_selinux_file_context (user_home) != 0) { -+ if (set_selinux_file_context (user_home, NULL) != 0) { - fail_exit (E_HOMEDIR); - } - #endif diff --git a/SOURCES/shadow-4.1.5.1-selinux-perms.patch b/SOURCES/shadow-4.1.5.1-selinux-perms.patch deleted file mode 100644 index 3c70296..0000000 --- a/SOURCES/shadow-4.1.5.1-selinux-perms.patch +++ /dev/null @@ -1,289 +0,0 @@ -diff -up shadow-4.1.5.1/src/chgpasswd.c.selinux-perms shadow-4.1.5.1/src/chgpasswd.c ---- shadow-4.1.5.1/src/chgpasswd.c.selinux-perms 2016-05-04 13:44:55.633787764 +0200 -+++ shadow-4.1.5.1/src/chgpasswd.c 2016-05-30 12:01:30.421587253 +0200 -@@ -39,6 +39,13 @@ - #include - #include - #include -+#ifdef WITH_SELINUX -+#include -+#include -+#endif -+#ifdef WITH_LIBAUDIT -+#include -+#endif - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - #include "pam_defs.h" -@@ -76,6 +83,9 @@ static bool sgr_locked = false; - #endif - static bool gr_locked = false; - -+/* The name of the caller */ -+static char *myname = NULL; -+ - /* local function prototypes */ - static void fail_exit (int code); - static /*@noreturn@*/void usage (int status); -@@ -300,6 +310,63 @@ static void check_perms (void) - #endif /* ACCT_TOOLS_SETUID */ - } - -+#ifdef WITH_SELINUX -+static int -+log_callback (int type, const char *fmt, ...) -+{ -+ int audit_fd; -+ va_list ap; -+ -+ va_start(ap, fmt); -+#ifdef WITH_AUDIT -+ audit_fd = audit_open(); -+ -+ if (audit_fd >= 0) { -+ char *buf; -+ -+ if (vasprintf (&buf, fmt, ap) < 0) -+ goto ret; -+ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, -+ NULL, 0); -+ audit_close(audit_fd); -+ free(buf); -+ goto ret; -+ } -+ -+#endif -+ vsyslog (LOG_USER | LOG_INFO, fmt, ap); -+ret: -+ va_end(ap); -+ return 0; -+} -+ -+static void -+selinux_check_root (void) -+{ -+ int status = -1; -+ security_context_t user_context; -+ union selinux_callback old_callback; -+ -+ if (is_selinux_enabled() < 1) -+ return; -+ -+ old_callback = selinux_get_callback(SELINUX_CB_LOG); -+ /* setup callbacks */ -+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); -+ if ((status = getprevcon(&user_context)) < 0) { -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ exit(1); -+ } -+ -+ status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); -+ -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ freecon(user_context); -+ if (status != 0 && security_getenforce() != 0) -+ exit(1); -+} -+#endif -+ - /* - * open_files - lock and open the group databases - */ -@@ -393,6 +460,7 @@ int main (int argc, char **argv) - - const struct group *gr; - struct group newgr; -+ struct passwd *pw = NULL; - int errors = 0; - int line = 0; - -@@ -408,8 +476,33 @@ int main (int argc, char **argv) - - OPENLOG ("chgpasswd"); - -+#ifdef WITH_AUDIT -+ audit_help_open (); -+#endif -+ -+ /* -+ * Determine the name of the user that invoked this command. This -+ * is really hit or miss because there are so many ways that command -+ * can be executed and so many ways to trip up the routines that -+ * report the user name. -+ */ -+ pw = get_my_pwent (); -+ if (NULL == pw) { -+ fprintf (stderr, _("%s: Cannot determine your user name.\n"), -+ Prog); -+ SYSLOG ((LOG_WARN, -+ "Cannot determine the user name of the caller (UID %lu)", -+ (unsigned long) getuid ())); -+ exit (E_NOPERM); -+ } -+ myname = xstrdup (pw->pw_name); -+ - check_perms (); - -+#ifdef WITH_SELINUX -+ selinux_check_root (); -+#endif -+ - #ifdef SHADOWGRP - is_shadow_grp = sgr_file_present (); - #endif -@@ -533,6 +626,15 @@ int main (int argc, char **argv) - newgr.gr_passwd = cp; - } - -+#ifdef WITH_AUDIT -+ { -+ -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "change-password", -+ myname, AUDIT_NO_ID, gr->gr_name, -+ SHADOW_AUDIT_SUCCESS); -+ } -+#endif - /* - * The updated group file entry is then put back and will - * be written to the group file later, after all the -diff -up shadow-4.1.5.1/src/chpasswd.c.selinux-perms shadow-4.1.5.1/src/chpasswd.c ---- shadow-4.1.5.1/src/chpasswd.c.selinux-perms 2016-05-04 13:44:55.633787764 +0200 -+++ shadow-4.1.5.1/src/chpasswd.c 2016-05-30 12:01:42.877859957 +0200 -@@ -39,6 +39,13 @@ - #include - #include - #include -+#ifdef WITH_SELINUX -+#include -+#include -+#endif -+#ifdef WITH_LIBAUDIT -+#include -+#endif - #ifdef USE_PAM - #include "pam_defs.h" - #endif /* USE_PAM */ -@@ -297,6 +304,63 @@ static void check_perms (void) - #endif /* USE_PAM */ - } - -+#ifdef WITH_SELINUX -+static int -+log_callback (int type, const char *fmt, ...) -+{ -+ int audit_fd; -+ va_list ap; -+ -+ va_start(ap, fmt); -+#ifdef WITH_AUDIT -+ audit_fd = audit_open(); -+ -+ if (audit_fd >= 0) { -+ char *buf; -+ -+ if (vasprintf (&buf, fmt, ap) < 0) -+ goto ret; -+ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, -+ NULL, 0); -+ audit_close(audit_fd); -+ free(buf); -+ goto ret; -+ } -+ -+#endif -+ vsyslog (LOG_USER | LOG_INFO, fmt, ap); -+ret: -+ va_end(ap); -+ return 0; -+} -+ -+static void -+selinux_check_root (void) -+{ -+ int status = -1; -+ security_context_t user_context; -+ union selinux_callback old_callback; -+ -+ if (is_selinux_enabled() < 1) -+ return; -+ -+ old_callback = selinux_get_callback(SELINUX_CB_LOG); -+ /* setup callbacks */ -+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); -+ if ((status = getprevcon(&user_context)) < 0) { -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ exit(1); -+ } -+ -+ status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); -+ -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ freecon(user_context); -+ if (status != 0 && security_getenforce() != 0) -+ exit(1); -+} -+#endif -+ - /* - * open_files - lock and open the password databases - */ -@@ -405,8 +469,16 @@ int main (int argc, char **argv) - - OPENLOG ("chpasswd"); - -+#ifdef WITH_AUDIT -+ audit_help_open (); -+#endif -+ - check_perms (); - -+#ifdef WITH_SELINUX -+ selinux_check_root (); -+#endif -+ - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -@@ -563,6 +635,11 @@ int main (int argc, char **argv) - newpw.pw_passwd = cp; - } - -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -+ "updating-password", -+ pw->pw_name, (unsigned int) pw->pw_uid, 1); -+#endif - /* - * The updated password file entry is then put back and will - * be written to the password file later, after all the -diff -up shadow-4.1.5.1/src/Makefile.am.selinux-perms shadow-4.1.5.1/src/Makefile.am ---- shadow-4.1.5.1/src/Makefile.am.selinux-perms 2016-05-04 13:44:55.647788082 +0200 -+++ shadow-4.1.5.1/src/Makefile.am 2016-05-27 16:04:49.446582632 +0200 -@@ -79,9 +79,9 @@ endif - - chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) - chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) --chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT) -+chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBAUDIT) $(LIBCRYPT) - chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) --chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) -+chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBAUDIT) $(LIBCRYPT) - gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) - groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) - groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) -diff -up shadow-4.1.5.1/src/Makefile.in.selinux-perms shadow-4.1.5.1/src/Makefile.in ---- shadow-4.1.5.1/src/Makefile.in.selinux-perms 2016-05-04 13:44:55.647788082 +0200 -+++ shadow-4.1.5.1/src/Makefile.in 2016-05-27 16:04:49.447582654 +0200 -@@ -437,9 +437,9 @@ AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/l - @USE_PAM_TRUE@LIBCRYPT_NOPAM = - chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) - chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) --chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT) -+chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBAUDIT) $(LIBCRYPT) - chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) --chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) -+chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBAUDIT) $(LIBCRYPT) - gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) - groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) - groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) diff --git a/SOURCES/shadow-4.1.5.1-selinux.patch b/SOURCES/shadow-4.1.5.1-selinux.patch deleted file mode 100644 index 4ac32d2..0000000 --- a/SOURCES/shadow-4.1.5.1-selinux.patch +++ /dev/null @@ -1,99 +0,0 @@ -diff -up shadow-4.1.5.1/lib/semanage.c.selinux shadow-4.1.5.1/lib/semanage.c ---- shadow-4.1.5.1/lib/semanage.c.selinux 2012-01-08 17:35:44.000000000 +0100 -+++ shadow-4.1.5.1/lib/semanage.c 2014-09-10 10:11:55.417506128 +0200 -@@ -294,6 +294,9 @@ int set_seuser (const char *login_name, - - ret = 0; - -+ /* drop obsolete matchpathcon cache */ -+ matchpathcon_fini(); -+ - done: - semanage_seuser_key_free (key); - semanage_handle_destroy (handle); -@@ -369,6 +372,10 @@ int del_seuser (const char *login_name) - } - - ret = 0; -+ -+ /* drop obsolete matchpathcon cache */ -+ matchpathcon_fini(); -+ - done: - semanage_handle_destroy (handle); - return ret; -diff -up shadow-4.1.5.1/src/useradd.c.selinux shadow-4.1.5.1/src/useradd.c ---- shadow-4.1.5.1/src/useradd.c.selinux 2014-09-10 10:10:18.791280619 +0200 -+++ shadow-4.1.5.1/src/useradd.c 2014-09-10 10:10:18.798280781 +0200 -@@ -1850,6 +1850,7 @@ static void create_mail (void) - */ - int main (int argc, char **argv) - { -+ int rv = E_SUCCESS; - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - pam_handle_t *pamh = NULL; -@@ -2037,10 +2038,33 @@ int main (int argc, char **argv) - - usr_update (); - -+ close_files (); -+ -+ nscd_flush_cache ("passwd"); -+ nscd_flush_cache ("group"); -+ -+#ifdef WITH_SELINUX -+ if (Zflg && *user_selinux) { -+ if (is_selinux_enabled () > 0) { -+ if (set_seuser (user_name, user_selinux) != 0) { -+ fprintf (stderr, -+ _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), -+ Prog, user_name, user_selinux); -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_ADD_USER, Prog, -+ "adding SELinux user mapping", -+ user_name, (unsigned int) user_id, 0); -+#endif /* WITH_AUDIT */ -+ rv = E_SE_UPDATE; -+ } -+ } -+ } -+#endif -+ - if (mflg) { - create_home (); - if (home_added) { -- copy_tree (def_template, user_home, false, false, -+ copy_tree (def_template, user_home, false, true, - (uid_t)-1, user_id, (gid_t)-1, user_gid); - } else { - fprintf (stderr, -@@ -2056,27 +2080,6 @@ int main (int argc, char **argv) - create_mail (); - } - -- close_files (); -- --#ifdef WITH_SELINUX -- if (Zflg) { -- if (set_seuser (user_name, user_selinux) != 0) { -- fprintf (stderr, -- _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), -- Prog, user_name, user_selinux); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding SELinux user mapping", -- user_name, (unsigned int) user_id, 0); --#endif /* WITH_AUDIT */ -- fail_exit (E_SE_UPDATE); -- } -- } --#endif /* WITH_SELINUX */ -- -- nscd_flush_cache ("passwd"); -- nscd_flush_cache ("group"); -- -- return E_SUCCESS; -+ return rv; - } - diff --git a/SOURCES/shadow-4.1.5.1-userdel-helpfix.patch b/SOURCES/shadow-4.1.5.1-userdel-helpfix.patch index b79baee..075f482 100644 --- a/SOURCES/shadow-4.1.5.1-userdel-helpfix.patch +++ b/SOURCES/shadow-4.1.5.1-userdel-helpfix.patch @@ -1,7 +1,8 @@ -diff -up shadow-4.1.5.1/src/userdel.c.userdel shadow-4.1.5.1/src/userdel.c ---- shadow-4.1.5.1/src/userdel.c.userdel 2012-05-25 13:51:55.000000000 +0200 -+++ shadow-4.1.5.1/src/userdel.c 2014-02-12 11:40:30.707686132 +0100 -@@ -130,8 +130,9 @@ static void usage (int status) +Index: shadow-4.5/src/userdel.c +=================================================================== +--- shadow-4.5.orig/src/userdel.c ++++ shadow-4.5/src/userdel.c +@@ -143,8 +143,9 @@ static void usage (int status) "\n" "Options:\n"), Prog); diff --git a/SOURCES/shadow-4.1.5.1-usermod-passwd.patch b/SOURCES/shadow-4.1.5.1-usermod-passwd.patch deleted file mode 100644 index 8096cfd..0000000 --- a/SOURCES/shadow-4.1.5.1-usermod-passwd.patch +++ /dev/null @@ -1,63 +0,0 @@ -diff -up shadow-4.1.5.1/src/usermod.c.passwd shadow-4.1.5.1/src/usermod.c ---- shadow-4.1.5.1/src/usermod.c.passwd 2015-12-17 14:05:47.959743073 +0100 -+++ shadow-4.1.5.1/src/usermod.c 2015-12-18 12:42:28.290405529 +0100 -@@ -360,14 +360,17 @@ static char *new_pw_passwd (char *pw_pas - strcat (buf, pw_pass); - pw_pass = buf; - } else if (Uflg && pw_pass[0] == '!') { -- char *s; -+ char *s = pw_pass; - -- if (pw_pass[1] == '\0') { -+ while ('!' == *s) -+ ++s; -+ -+ if (*s == '\0') { - fprintf (stderr, - _("%s: unlocking the user's password would result in a passwordless account.\n" - "You should set a password with usermod -p to unlock this user's password.\n"), - Prog); -- return pw_pass; -+ return NULL; - } - - #ifdef WITH_AUDIT -@@ -376,12 +379,15 @@ static char *new_pw_passwd (char *pw_pas - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); -- s = pw_pass; -- while ('\0' != *s) { -- *s = *(s + 1); -- s++; -- } -+ memmove (pw_pass, s, strlen (s) + 1); - } else if (pflg) { -+ if (strchr (user_pass, ':') != NULL) { -+ fprintf (stderr, -+ _("%s: The password field cannot contain a colon character.\n"), -+ Prog); -+ return NULL; -+ -+ } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "updating-password", -@@ -430,6 +436,8 @@ static void new_pwent (struct passwd *pw - if ( (!is_shadow_pwd) - || (strcmp (pwent->pw_passwd, SHADOW_PASSWD_STRING) != 0)) { - pwent->pw_passwd = new_pw_passwd (pwent->pw_passwd); -+ if (pwent->pw_passwd == NULL) -+ fail_exit (E_PW_UPDATE); - } - - if (uflg) { -@@ -544,6 +552,8 @@ static void new_spent (struct spwd *spen - * + aging has been requested - */ - spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp); -+ if (spent->sp_pwdp == NULL) -+ fail_exit(E_PW_UPDATE); - - if (pflg) { - spent->sp_lstchg = (long) time ((time_t *) 0) / SCALE; diff --git a/SOURCES/shadow-4.1.5.1.tar.bz2.sig b/SOURCES/shadow-4.1.5.1.tar.bz2.sig deleted file mode 100644 index d0f1167..0000000 Binary files a/SOURCES/shadow-4.1.5.1.tar.bz2.sig and /dev/null differ diff --git a/SOURCES/shadow-4.2.1-date-parsing.patch b/SOURCES/shadow-4.2.1-date-parsing.patch new file mode 100644 index 0000000..2a798d0 --- /dev/null +++ b/SOURCES/shadow-4.2.1-date-parsing.patch @@ -0,0 +1,69 @@ +Index: shadow-4.5/libmisc/getdate.y +=================================================================== +--- shadow-4.5.orig/libmisc/getdate.y ++++ shadow-4.5/libmisc/getdate.y +@@ -152,6 +152,7 @@ static int yyHaveDay; + static int yyHaveRel; + static int yyHaveTime; + static int yyHaveZone; ++static int yyHaveYear; + static int yyTimezone; + static int yyDay; + static int yyHour; +@@ -293,18 +294,21 @@ date : tUNUMBER '/' tUNUMBER { + yyDay = $3; + yyYear = $5; + } ++ yyHaveYear++; + } + | tUNUMBER tSNUMBER tSNUMBER { + /* ISO 8601 format. yyyy-mm-dd. */ + yyYear = $1; + yyMonth = -$2; + yyDay = -$3; ++ yyHaveYear++; + } + | tUNUMBER tMONTH tSNUMBER { + /* e.g. 17-JUN-1992. */ + yyDay = $1; + yyMonth = $2; + yyYear = -$3; ++ yyHaveYear++; + } + | tMONTH tUNUMBER { + yyMonth = $1; +@@ -314,6 +318,7 @@ date : tUNUMBER '/' tUNUMBER { + yyMonth = $1; + yyDay = $2; + yyYear = $4; ++ yyHaveYear++; + } + | tUNUMBER tMONTH { + yyMonth = $2; +@@ -323,6 +328,7 @@ date : tUNUMBER '/' tUNUMBER { + yyMonth = $2; + yyDay = $1; + yyYear = $3; ++ yyHaveYear++; + } + ; + +@@ -395,7 +401,8 @@ relunit : tUNUMBER tYEAR_UNIT { + + number : tUNUMBER + { +- if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0)) ++ if ((yyHaveTime != 0 || $1 >= 100) && !yyHaveYear ++ && (yyHaveDate != 0) && (yyHaveRel == 0)) + yyYear = $1; + else + { +@@ -802,7 +809,7 @@ yylex (void) + return LookupWord (buff); + } + if (c != '(') +- return *yyInput++; ++ return (unsigned char)*yyInput++; + Count = 0; + do + { diff --git a/SOURCES/shadow-4.2.1-no-lock-dos.patch b/SOURCES/shadow-4.2.1-no-lock-dos.patch new file mode 100644 index 0000000..c6873e9 --- /dev/null +++ b/SOURCES/shadow-4.2.1-no-lock-dos.patch @@ -0,0 +1,16 @@ +Index: shadow-4.5/lib/commonio.c +=================================================================== +--- shadow-4.5.orig/lib/commonio.c ++++ shadow-4.5/lib/commonio.c +@@ -140,7 +140,10 @@ static int do_lock_file (const char *fil + int retval; + char buf[32]; + +- fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600); ++ /* We depend here on the fact, that the file name is pid-specific. ++ * So no O_EXCL here and no DoS. ++ */ ++ fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600); + if (-1 == fd) { + if (log) { + (void) fprintf (stderr, diff --git a/SOURCES/shadow-4.2.1-null-tm.patch b/SOURCES/shadow-4.2.1-null-tm.patch new file mode 100644 index 0000000..b1dd1c4 --- /dev/null +++ b/SOURCES/shadow-4.2.1-null-tm.patch @@ -0,0 +1,91 @@ +Index: shadow-4.5/src/faillog.c +=================================================================== +--- shadow-4.5.orig/src/faillog.c ++++ shadow-4.5/src/faillog.c +@@ -163,10 +163,14 @@ static void print_one (/*@null@*/const s + } + + tm = localtime (&fl.fail_time); ++ if (tm == NULL) { ++ cp = "(unknown)"; ++ } else { + #ifdef HAVE_STRFTIME +- strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm); +- cp = ptime; ++ strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm); ++ cp = ptime; + #endif ++ } + printf ("%-9s %5d %5d ", + pw->pw_name, fl.fail_cnt, fl.fail_max); + /* FIXME: cp is not defined ifndef HAVE_STRFTIME */ +Index: shadow-4.5/src/chage.c +=================================================================== +--- shadow-4.5.orig/src/chage.c ++++ shadow-4.5/src/chage.c +@@ -168,6 +168,10 @@ static void date_to_str (char *buf, size + struct tm *tp; + + tp = gmtime (&date); ++ if (tp == NULL) { ++ (void) snprintf (buf, maxsize, "(unknown)"); ++ return; ++ } + #ifdef HAVE_STRFTIME + (void) strftime (buf, maxsize, "%Y-%m-%d", tp); + #else +Index: shadow-4.5/src/lastlog.c +=================================================================== +--- shadow-4.5.orig/src/lastlog.c ++++ shadow-4.5/src/lastlog.c +@@ -158,13 +158,17 @@ static void print_one (/*@null@*/const s + + ll_time = ll.ll_time; + tm = localtime (&ll_time); ++ if (tm == NULL) { ++ cp = "(unknown)"; ++ } else { + #ifdef HAVE_STRFTIME +- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); +- cp = ptime; ++ strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); ++ cp = ptime; + #else +- cp = asctime (tm); +- cp[24] = '\0'; ++ cp = asctime (tm); ++ cp[24] = '\0'; + #endif ++ } + + if (ll.ll_time == (time_t) 0) { + cp = _("**Never logged in**\0"); +Index: shadow-4.5/src/passwd.c +=================================================================== +--- shadow-4.5.orig/src/passwd.c ++++ shadow-4.5/src/passwd.c +@@ -455,6 +455,9 @@ static /*@observer@*/const char *date_to + struct tm *tm; + + tm = gmtime (&t); ++ if (tm == NULL) { ++ return "(unknown)"; ++ } + #ifdef HAVE_STRFTIME + (void) strftime (buf, sizeof buf, "%m/%d/%Y", tm); + #else /* !HAVE_STRFTIME */ +Index: shadow-4.5/src/usermod.c +=================================================================== +--- shadow-4.5.orig/src/usermod.c ++++ shadow-4.5/src/usermod.c +@@ -210,6 +210,10 @@ static void date_to_str (/*@unique@*//*@ + } else { + time_t t = (time_t) date; + tp = gmtime (&t); ++ if (tp == NULL) { ++ strncpy (buf, "unknown", maxsize); ++ return; ++ } + #ifdef HAVE_STRFTIME + strftime (buf, maxsize, "%Y-%m-%d", tp); + #else diff --git a/SOURCES/shadow-4.3.1-manfix.patch b/SOURCES/shadow-4.3.1-manfix.patch new file mode 100644 index 0000000..43d5e9a --- /dev/null +++ b/SOURCES/shadow-4.3.1-manfix.patch @@ -0,0 +1,329 @@ +Index: shadow-4.5/man/groupmems.8.xml +=================================================================== +--- shadow-4.5.orig/man/groupmems.8.xml ++++ shadow-4.5/man/groupmems.8.xml +@@ -179,20 +179,10 @@ + + SETUP + +- The groupmems executable should be in mode +- 2770 as user root and in group +- groups. The system administrator can add users to +- group groups to allow or disallow them using the +- groupmems utility to manage their own group +- membership list. ++ In this operating system the groupmems executable ++ is not setuid and regular users cannot use it to manipulate ++ the membership of their own group. + +- +- +- $ groupadd -r groups +- $ chmod 2770 groupmems +- $ chown root.groups groupmems +- $ groupmems -g groups -a gk4 +- + + + +Index: shadow-4.5/man/chage.1.xml +=================================================================== +--- shadow-4.5.orig/man/chage.1.xml ++++ shadow-4.5/man/chage.1.xml +@@ -102,6 +102,9 @@ + Set the number of days since January 1st, 1970 when the password + was last changed. The date may also be expressed in the format + YYYY-MM-DD (or the format more commonly used in your area). ++ If the LAST_DAY is set to ++ 0 the user is forced to change his password ++ on the next log on. + + + +@@ -119,6 +122,13 @@ + system again. + + ++ For example the following can be used to set an account to expire ++ in 180 days: ++ ++ ++ chage -E $(date -d +180days +%Y-%m-%d) ++ ++ + Passing the number -1 as the + EXPIRE_DATE will remove an account + expiration date. +@@ -233,6 +243,18 @@ + The chage program requires a shadow password file to + be available. + ++ ++ The chage program will report only the information from the shadow ++ password file. This implies that configuration from other sources ++ (e.g. LDAP or empty password hash field from the passwd file) that ++ affect the user's login will not be shown in the chage output. ++ ++ ++ The chage program will also not report any ++ inconsistency between the shadow and passwd files (e.g. missing x in ++ the passwd file). The pwck can be used to check ++ for this kind of inconsistencies. ++ + The chage command is restricted to the root + user, except for the option, which may be used by + an unprivileged user to determine when their password or account is due +Index: shadow-4.5/man/ja/man5/login.defs.5 +=================================================================== +--- shadow-4.5.orig/man/ja/man5/login.defs.5 ++++ shadow-4.5/man/ja/man5/login.defs.5 +@@ -147,10 +147,6 @@ PASS_MAX_DAYS, PASS_MIN_DAYS, PASS_WARN_ + shadow パスワード機能のどのプログラムが + どのパラメータを使用するかを示したものである。 + .na +-.IP chfn 12 +-CHFN_AUTH CHFN_RESTRICT +-.IP chsh 12 +-CHFN_AUTH + .IP groupadd 12 + GID_MAX GID_MIN + .IP newusers 12 +Index: shadow-4.5/man/login.defs.5.xml +=================================================================== +--- shadow-4.5.orig/man/login.defs.5.xml ++++ shadow-4.5/man/login.defs.5.xml +@@ -162,6 +162,17 @@ + long numeric parameters is machine-dependent. + + ++ ++ Please note that the parameters in this configuration file control the ++ behavior of the tools from the shadow-utils component. None of these ++ tools uses the PAM mechanism, and the utilities that use PAM (such as the ++ passwd command) should be configured elsewhere. The only values that ++ affect PAM modules are ENCRYPT_METHOD and SHA_CRYPT_MAX_ROUNDS ++ for pam_unix module, FAIL_DELAY for pam_faildelay module, ++ and UMASK for pam_umask module. Refer to ++ pam(8) for more information. ++ ++ + The following configuration items are provided: + + +@@ -252,16 +263,6 @@ + + + +- chfn +- +- +- CHFN_AUTH +- CHFN_RESTRICT +- LOGIN_STRING +- +- +- +- + chgpasswd + + +@@ -282,14 +283,6 @@ + + + +- +- chsh +- +- +- CHSH_AUTH LOGIN_STRING +- +- +- + + + +@@ -350,34 +343,6 @@ + + + +- +- login +- +- +- CONSOLE +- CONSOLE_GROUPS DEFAULT_HOME +- ENV_HZ ENV_PATH ENV_SUPATH +- ENV_TZ ENVIRON_FILE +- ERASECHAR FAIL_DELAY +- FAILLOG_ENAB +- FAKE_SHELL +- FTMP_FILE +- HUSHLOGIN_FILE +- ISSUE_FILE +- KILLCHAR +- LASTLOG_ENAB +- LOGIN_RETRIES +- LOGIN_STRING +- LOGIN_TIMEOUT LOG_OK_LOGINS LOG_UNKFAIL_ENAB +- MAIL_CHECK_ENAB MAIL_DIR MAIL_FILE +- MOTD_FILE NOLOGINS_FILE PORTTIME_CHECKS_ENAB +- QUOTAS_ENAB +- TTYGROUP TTYPERM TTYTYPE_FILE +- ULIMIT UMASK +- USERGROUPS_ENAB +- +- +- + + + newgrp / sg +@@ -405,17 +370,6 @@ + + + +- +- passwd +- +- +- ENCRYPT_METHOD MD5_CRYPT_ENAB OBSCURE_CHECKS_ENAB +- PASS_ALWAYS_WARN PASS_CHANGE_TRIES PASS_MAX_LEN PASS_MIN_LEN +- SHA_CRYPT_MAX_ROUNDS +- SHA_CRYPT_MIN_ROUNDS +- +- +- + + pwck + +@@ -442,32 +396,6 @@ + + + +- +- su +- +- +- CONSOLE +- CONSOLE_GROUPS DEFAULT_HOME +- ENV_HZ ENVIRON_FILE +- ENV_PATH ENV_SUPATH +- ENV_TZ LOGIN_STRING MAIL_CHECK_ENAB +- MAIL_DIR MAIL_FILE QUOTAS_ENAB +- SULOG_FILE SU_NAME +- SU_WHEEL_ONLY +- SYSLOG_SU_ENAB +- USERGROUPS_ENAB +- +- +- +- +- sulogin +- +- +- ENV_HZ +- ENV_TZ +- +- +- + + useradd + +Index: shadow-4.5/man/shadow.5.xml +=================================================================== +--- shadow-4.5.orig/man/shadow.5.xml ++++ shadow-4.5/man/shadow.5.xml +@@ -129,7 +129,7 @@ + + + The date of the last password change, expressed as the number +- of days since Jan 1, 1970. ++ of days since Jan 1, 1970 00:00 UTC. + + + The value 0 has a special meaning, which is that the user +@@ -208,8 +208,8 @@ + + + After expiration of the password and this expiration period is +- elapsed, no login is possible using the current user's +- password. The user should contact her administrator. ++ elapsed, no login is possible for the user. ++ The user should contact her administrator. + + + An empty field means that there are no enforcement of an +@@ -224,7 +224,7 @@ + + + The date of expiration of the account, expressed as the number +- of days since Jan 1, 1970. ++ of days since Jan 1, 1970 00:00 UTC. + + + Note that an account expiration differs from a password +Index: shadow-4.5/man/useradd.8.xml +=================================================================== +--- shadow-4.5.orig/man/useradd.8.xml ++++ shadow-4.5/man/useradd.8.xml +@@ -347,6 +347,11 @@ + is not enabled, no home + directories are created. + ++ ++ The directory where the user's home directory is created must ++ exist and have proper SELinux context and permissions. Otherwise ++ the user's home directory cannot be created or accessed. ++ + + + +Index: shadow-4.5/man/usermod.8.xml +=================================================================== +--- shadow-4.5.orig/man/usermod.8.xml ++++ shadow-4.5/man/usermod.8.xml +@@ -132,7 +132,8 @@ + If the + option is given, the contents of the current home directory will + be moved to the new home directory, which is created if it does +- not already exist. ++ not already exist. If the current home directory does not exist ++ the new home directory will not be created. + + + +@@ -256,7 +257,8 @@ + + + Move the content of the user's home directory to the new +- location. ++ location. If the current home directory does not exist ++ the new home directory will not be created. + + + This option is only valid in combination with the +diff --git a/man/login.defs.d/SUB_GID_COUNT.xml b/man/login.defs.d/SUB_GID_COUNT.xml +index 01ace007..93fe7421 100644 +--- a/man/login.defs.d/SUB_GID_COUNT.xml ++++ b/man/login.defs.d/SUB_GID_COUNT.xml +@@ -42,7 +42,7 @@ + + The default values for , + , +- are respectively 100000, 600100000 and 10000. ++ are respectively 100000, 600100000 and 65536. + + + +diff --git a/man/login.defs.d/SUB_UID_COUNT.xml b/man/login.defs.d/SUB_UID_COUNT.xml +index 5ad812f7..516417b7 100644 +--- a/man/login.defs.d/SUB_UID_COUNT.xml ++++ b/man/login.defs.d/SUB_UID_COUNT.xml +@@ -42,7 +42,7 @@ + + The default values for , + , +- are respectively 100000, 600100000 and 10000. ++ are respectively 100000, 600100000 and 65536. + + + diff --git a/SOURCES/shadow-4.3.1-selinux-perms.patch b/SOURCES/shadow-4.3.1-selinux-perms.patch new file mode 100644 index 0000000..8550150 --- /dev/null +++ b/SOURCES/shadow-4.3.1-selinux-perms.patch @@ -0,0 +1,277 @@ +Index: shadow-4.5/src/chgpasswd.c +=================================================================== +--- shadow-4.5.orig/src/chgpasswd.c ++++ shadow-4.5/src/chgpasswd.c +@@ -39,6 +39,13 @@ + #include + #include + #include ++#ifdef WITH_SELINUX ++#include ++#include ++#endif ++#ifdef WITH_LIBAUDIT ++#include ++#endif + #ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + #include "pam_defs.h" +@@ -76,6 +83,9 @@ static bool sgr_locked = false; + #endif + static bool gr_locked = false; + ++/* The name of the caller */ ++static char *myname = NULL; ++ + /* local function prototypes */ + static void fail_exit (int code); + static /*@noreturn@*/void usage (int status); +@@ -300,6 +310,63 @@ static void check_perms (void) + #endif /* ACCT_TOOLS_SETUID */ + } + ++#ifdef WITH_SELINUX ++static int ++log_callback (int type, const char *fmt, ...) ++{ ++ int audit_fd; ++ va_list ap; ++ ++ va_start(ap, fmt); ++#ifdef WITH_AUDIT ++ audit_fd = audit_open(); ++ ++ if (audit_fd >= 0) { ++ char *buf; ++ ++ if (vasprintf (&buf, fmt, ap) < 0) ++ goto ret; ++ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, ++ NULL, 0); ++ audit_close(audit_fd); ++ free(buf); ++ goto ret; ++ } ++ ++#endif ++ vsyslog (LOG_USER | LOG_INFO, fmt, ap); ++ret: ++ va_end(ap); ++ return 0; ++} ++ ++static void ++selinux_check_root (void) ++{ ++ int status = -1; ++ security_context_t user_context; ++ union selinux_callback old_callback; ++ ++ if (is_selinux_enabled() < 1) ++ return; ++ ++ old_callback = selinux_get_callback(SELINUX_CB_LOG); ++ /* setup callbacks */ ++ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); ++ if ((status = getprevcon(&user_context)) < 0) { ++ selinux_set_callback(SELINUX_CB_LOG, old_callback); ++ exit(1); ++ } ++ ++ status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); ++ ++ selinux_set_callback(SELINUX_CB_LOG, old_callback); ++ freecon(user_context); ++ if (status != 0 && security_getenforce() != 0) ++ exit(1); ++} ++#endif ++ + /* + * open_files - lock and open the group databases + */ +@@ -393,6 +460,7 @@ int main (int argc, char **argv) + + const struct group *gr; + struct group newgr; ++ struct passwd *pw = NULL; + int errors = 0; + int line = 0; + +@@ -408,8 +476,33 @@ int main (int argc, char **argv) + + OPENLOG ("chgpasswd"); + ++#ifdef WITH_AUDIT ++ audit_help_open (); ++#endif ++ ++ /* ++ * Determine the name of the user that invoked this command. This ++ * is really hit or miss because there are so many ways that command ++ * can be executed and so many ways to trip up the routines that ++ * report the user name. ++ */ ++ pw = get_my_pwent (); ++ if (NULL == pw) { ++ fprintf (stderr, _("%s: Cannot determine your user name.\n"), ++ Prog); ++ SYSLOG ((LOG_WARN, ++ "Cannot determine the user name of the caller (UID %lu)", ++ (unsigned long) getuid ())); ++ exit (E_NOPERM); ++ } ++ myname = xstrdup (pw->pw_name); ++ + check_perms (); + ++#ifdef WITH_SELINUX ++ selinux_check_root (); ++#endif ++ + #ifdef SHADOWGRP + is_shadow_grp = sgr_file_present (); + #endif +@@ -536,6 +629,15 @@ int main (int argc, char **argv) + newgr.gr_passwd = cp; + } + ++#ifdef WITH_AUDIT ++ { ++ ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "change-password", ++ myname, AUDIT_NO_ID, gr->gr_name, ++ SHADOW_AUDIT_SUCCESS); ++ } ++#endif + /* + * The updated group file entry is then put back and will + * be written to the group file later, after all the +Index: shadow-4.5/src/chpasswd.c +=================================================================== +--- shadow-4.5.orig/src/chpasswd.c ++++ shadow-4.5/src/chpasswd.c +@@ -39,6 +39,13 @@ + #include + #include + #include ++#ifdef WITH_SELINUX ++#include ++#include ++#endif ++#ifdef WITH_LIBAUDIT ++#include ++#endif + #ifdef USE_PAM + #include "pam_defs.h" + #endif /* USE_PAM */ +@@ -297,6 +304,63 @@ static void check_perms (void) + #endif /* USE_PAM */ + } + ++#ifdef WITH_SELINUX ++static int ++log_callback (int type, const char *fmt, ...) ++{ ++ int audit_fd; ++ va_list ap; ++ ++ va_start(ap, fmt); ++#ifdef WITH_AUDIT ++ audit_fd = audit_open(); ++ ++ if (audit_fd >= 0) { ++ char *buf; ++ ++ if (vasprintf (&buf, fmt, ap) < 0) ++ goto ret; ++ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, ++ NULL, 0); ++ audit_close(audit_fd); ++ free(buf); ++ goto ret; ++ } ++ ++#endif ++ vsyslog (LOG_USER | LOG_INFO, fmt, ap); ++ret: ++ va_end(ap); ++ return 0; ++} ++ ++static void ++selinux_check_root (void) ++{ ++ int status = -1; ++ security_context_t user_context; ++ union selinux_callback old_callback; ++ ++ if (is_selinux_enabled() < 1) ++ return; ++ ++ old_callback = selinux_get_callback(SELINUX_CB_LOG); ++ /* setup callbacks */ ++ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); ++ if ((status = getprevcon(&user_context)) < 0) { ++ selinux_set_callback(SELINUX_CB_LOG, old_callback); ++ exit(1); ++ } ++ ++ status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); ++ ++ selinux_set_callback(SELINUX_CB_LOG, old_callback); ++ freecon(user_context); ++ if (status != 0 && security_getenforce() != 0) ++ exit(1); ++} ++#endif ++ + /* + * open_files - lock and open the password databases + */ +@@ -405,8 +469,16 @@ int main (int argc, char **argv) + + OPENLOG ("chpasswd"); + ++#ifdef WITH_AUDIT ++ audit_help_open (); ++#endif ++ + check_perms (); + ++#ifdef WITH_SELINUX ++ selinux_check_root (); ++#endif ++ + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ +@@ -566,6 +638,11 @@ int main (int argc, char **argv) + newpw.pw_passwd = cp; + } + ++#ifdef WITH_AUDIT ++ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, ++ "updating-password", ++ pw->pw_name, (unsigned int) pw->pw_uid, 1); ++#endif + /* + * The updated password file entry is then put back and will + * be written to the password file later, after all the +Index: shadow-4.5/src/Makefile.am +=================================================================== +--- shadow-4.5.orig/src/Makefile.am ++++ shadow-4.5/src/Makefile.am +@@ -87,9 +87,9 @@ chage_LDADD = $(LDADD) $(LIBPAM_SUID) + newuidmap_LDADD = $(LDADD) $(LIBSELINUX) + newgidmap_LDADD = $(LDADD) $(LIBSELINUX) + chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) +-chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT) ++chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBAUDIT) $(LIBCRYPT) + chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) +-chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) ++chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBAUDIT) $(LIBCRYPT) + gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) + groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) + groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) diff --git a/SOURCES/shadow-4.5-crypt_h.patch b/SOURCES/shadow-4.5-crypt_h.patch new file mode 100644 index 0000000..c8d19e4 --- /dev/null +++ b/SOURCES/shadow-4.5-crypt_h.patch @@ -0,0 +1,41 @@ +Index: shadow-4.5/configure.ac +=================================================================== +--- shadow-4.5.orig/configure.ac ++++ shadow-4.5/configure.ac +@@ -32,9 +32,9 @@ AC_HEADER_STDC + AC_HEADER_SYS_WAIT + AC_HEADER_STDBOOL + +-AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ +- utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \ +- utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \ ++AC_CHECK_HEADERS(crypt.h errno.h fcntl.h limits.h unistd.h sys/time.h \ ++ utmp.h utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h \ ++ paths.h utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \ + locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \ + attr/error_context.h) + +Index: shadow-4.5/lib/defines.h +=================================================================== +--- shadow-4.5.orig/lib/defines.h ++++ shadow-4.5/lib/defines.h +@@ -4,6 +4,8 @@ + #ifndef _DEFINES_H_ + #define _DEFINES_H_ + ++#include "config.h" ++ + #if HAVE_STDBOOL_H + # include + #else +@@ -94,6 +96,10 @@ char *strchr (), *strrchr (), *strtok () + # include + #endif + ++#if HAVE_CRYPT_H ++# include /* crypt(3) may be defined in here */ ++#endif ++ + #if TIME_WITH_SYS_TIME + # include + # include diff --git a/SOURCES/shadow-4.5-goodname.patch b/SOURCES/shadow-4.5-goodname.patch new file mode 100644 index 0000000..13e67d7 --- /dev/null +++ b/SOURCES/shadow-4.5-goodname.patch @@ -0,0 +1,110 @@ +Index: shadow-4.5/libmisc/chkname.c +=================================================================== +--- shadow-4.5.orig/libmisc/chkname.c ++++ shadow-4.5/libmisc/chkname.c +@@ -47,27 +47,46 @@ + #include "chkname.h" + + static bool is_valid_name (const char *name) +-{ ++{ + /* +- * User/group names must match [a-z_][a-z0-9_-]*[$] +- */ +- if (('\0' == *name) || +- !((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) { ++ * User/group names must match gnu e-regex: ++ * [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]? ++ * ++ * as a non-POSIX, extension, allow "$" as the last char for ++ * sake of Samba 3.x "add machine script" ++ * ++ * Also do not allow fully numeric names or just "." or "..". ++ */ ++ int numeric; ++ ++ if ('\0' == *name || ++ ('.' == *name && (('.' == name[1] && '\0' == name[2]) || ++ '\0' == name[1])) || ++ !((*name >= 'a' && *name <= 'z') || ++ (*name >= 'A' && *name <= 'Z') || ++ (*name >= '0' && *name <= '9') || ++ *name == '_' || ++ *name == '.')) { + return false; + } + ++ numeric = isdigit(*name); ++ + while ('\0' != *++name) { +- if (!(( ('a' <= *name) && ('z' >= *name) ) || +- ( ('0' <= *name) && ('9' >= *name) ) || +- ('_' == *name) || +- ('-' == *name) || +- ( ('$' == *name) && ('\0' == *(name + 1)) ) ++ if (!((*name >= 'a' && *name <= 'z') || ++ (*name >= 'A' && *name <= 'Z') || ++ (*name >= '0' && *name <= '9') || ++ *name == '_' || ++ *name == '.' || ++ *name == '-' || ++ (*name == '$' && name[1] == '\0') + )) { + return false; + } ++ numeric &= isdigit(*name); + } + +- return true; ++ return !numeric || getenv("SHADOW_ALLOW_ALL_NUMERIC_USER") != NULL; + } + + bool is_valid_user_name (const char *name) +Index: shadow-4.5/man/groupadd.8.xml +=================================================================== +--- shadow-4.5.orig/man/groupadd.8.xml ++++ shadow-4.5/man/groupadd.8.xml +@@ -256,10 +256,14 @@ + + CAVEATS + +- Groupnames must start with a lower case letter or an underscore, +- followed by lower case letters, digits, underscores, or dashes. +- They can end with a dollar sign. +- In regular expression terms: [a-z_][a-z0-9_-]*[$]? ++ Groupnames may contain only lower and upper case letters, digits, ++ underscores, or dashes. They can end with a dollar sign. ++ ++ Dashes are not allowed at the beginning of the groupname. ++ Fully numeric groupnames and groupnames . or .. are ++ also disallowed. ++ ++ In regular expression terms: [a-zA-Z0-9_.][a-zA-Z0-9_.-]*[$]? + + + Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long. +Index: shadow-4.5/man/useradd.8.xml +=================================================================== +--- shadow-4.5.orig/man/useradd.8.xml ++++ shadow-4.5/man/useradd.8.xml +@@ -633,10 +633,16 @@ + + + +- Usernames must start with a lower case letter or an underscore, +- followed by lower case letters, digits, underscores, or dashes. +- They can end with a dollar sign. +- In regular expression terms: [a-z_][a-z0-9_-]*[$]? ++ Usernames may contain only lower and upper case letters, digits, ++ underscores, or dashes. They can end with a dollar sign. ++ ++ Dashes are not allowed at the beginning of the username. ++ Fully numeric usernames and usernames . or .. are ++ also disallowed. It is not recommended to use usernames beginning ++ with . character as their home directories will be hidden in ++ the ls output. ++ ++ In regular expression terms: [a-zA-Z0-9_.][a-zA-Z0-9_.-]*[$]? + + + Usernames may only be up to 32 characters long. diff --git a/SOURCES/shadow-4.5-long-entry.patch b/SOURCES/shadow-4.5-long-entry.patch new file mode 100644 index 0000000..8670e75 --- /dev/null +++ b/SOURCES/shadow-4.5-long-entry.patch @@ -0,0 +1,84 @@ +diff -up shadow-4.5/lib/defines.h.long-entry shadow-4.5/lib/defines.h +--- shadow-4.5/lib/defines.h.long-entry 2014-09-01 16:36:40.000000000 +0200 ++++ shadow-4.5/lib/defines.h 2018-04-20 11:53:07.419308212 +0200 +@@ -382,4 +382,7 @@ extern char *strerror (); + # endif + #endif + ++/* Maximum length of passwd entry */ ++#define PASSWD_ENTRY_MAX_LENGTH 32768 ++ + #endif /* _DEFINES_H_ */ +diff -up shadow-4.5/lib/pwio.c.long-entry shadow-4.5/lib/pwio.c +--- shadow-4.5/lib/pwio.c.long-entry 2015-11-17 17:45:15.000000000 +0100 ++++ shadow-4.5/lib/pwio.c 2018-04-20 12:10:24.400837235 +0200 +@@ -79,7 +79,10 @@ static int passwd_put (const void *ent, + || (pw->pw_gid == (gid_t)-1) + || (valid_field (pw->pw_gecos, ":\n") == -1) + || (valid_field (pw->pw_dir, ":\n") == -1) +- || (valid_field (pw->pw_shell, ":\n") == -1)) { ++ || (valid_field (pw->pw_shell, ":\n") == -1) ++ || (strlen (pw->pw_name) + strlen (pw->pw_passwd) + ++ strlen (pw->pw_gecos) + strlen (pw->pw_dir) + ++ strlen (pw->pw_shell) + 100 > PASSWD_ENTRY_MAX_LENGTH)) { + return -1; + } + +diff -up shadow-4.5/lib/sgetpwent.c.long-entry shadow-4.5/lib/sgetpwent.c +--- shadow-4.5/lib/sgetpwent.c.long-entry 2014-09-01 16:36:40.000000000 +0200 ++++ shadow-4.5/lib/sgetpwent.c 2018-04-20 12:16:31.911513808 +0200 +@@ -57,7 +57,7 @@ + struct passwd *sgetpwent (const char *buf) + { + static struct passwd pwent; +- static char pwdbuf[1024]; ++ static char pwdbuf[PASSWD_ENTRY_MAX_LENGTH]; + register int i; + register char *cp; + char *fields[NFIELDS]; +@@ -67,8 +67,10 @@ struct passwd *sgetpwent (const char *bu + * the password structure remain valid. + */ + +- if (strlen (buf) >= sizeof pwdbuf) ++ if (strlen (buf) >= sizeof pwdbuf) { ++ fprintf (stderr, "Too long passwd entry encountered, file corruption?\n"); + return 0; /* fail if too long */ ++ } + strcpy (pwdbuf, buf); + + /* +diff -up shadow-4.5/lib/sgetspent.c.long-entry shadow-4.5/lib/sgetspent.c +--- shadow-4.5/lib/sgetspent.c.long-entry 2014-09-01 16:36:40.000000000 +0200 ++++ shadow-4.5/lib/sgetspent.c 2018-04-20 12:16:54.505056257 +0200 +@@ -48,7 +48,7 @@ + */ + struct spwd *sgetspent (const char *string) + { +- static char spwbuf[1024]; ++ static char spwbuf[PASSWD_ENTRY_MAX_LENGTH]; + static struct spwd spwd; + char *fields[FIELDS]; + char *cp; +@@ -61,6 +61,7 @@ struct spwd *sgetspent (const char *stri + */ + + if (strlen (string) >= sizeof spwbuf) { ++ fprintf (stderr, "Too long shadow entry encountered, file corruption?\n"); + return 0; /* fail if too long */ + } + strcpy (spwbuf, string); +diff -up shadow-4.5/lib/shadowio.c.long-entry shadow-4.5/lib/shadowio.c +--- shadow-4.5/lib/shadowio.c.long-entry 2016-12-07 06:30:41.000000001 +0100 ++++ shadow-4.5/lib/shadowio.c 2018-04-20 12:12:03.292171667 +0200 +@@ -79,7 +79,9 @@ static int shadow_put (const void *ent, + + if ( (NULL == sp) + || (valid_field (sp->sp_namp, ":\n") == -1) +- || (valid_field (sp->sp_pwdp, ":\n") == -1)) { ++ || (valid_field (sp->sp_pwdp, ":\n") == -1) ++ || (strlen (sp->sp_namp) + strlen (sp->sp_pwdp) + ++ 1000 > PASSWD_ENTRY_MAX_LENGTH)) { + return -1; + } + diff --git a/SOURCES/shadow-4.5-usermod-unlock.patch b/SOURCES/shadow-4.5-usermod-unlock.patch new file mode 100644 index 0000000..e2d70b5 --- /dev/null +++ b/SOURCES/shadow-4.5-usermod-unlock.patch @@ -0,0 +1,64 @@ +Index: shadow-4.5/src/usermod.c +=================================================================== +--- shadow-4.5.orig/src/usermod.c ++++ shadow-4.5/src/usermod.c +@@ -455,14 +455,17 @@ static char *new_pw_passwd (char *pw_pas + strcat (buf, pw_pass); + pw_pass = buf; + } else if (Uflg && pw_pass[0] == '!') { +- char *s; ++ char *s = pw_pass; + +- if (pw_pass[1] == '\0') { ++ while ('!' == *s) ++ ++s; ++ ++ if (*s == '\0') { + fprintf (stderr, + _("%s: unlocking the user's password would result in a passwordless account.\n" + "You should set a password with usermod -p to unlock this user's password.\n"), + Prog); +- return pw_pass; ++ return NULL; + } + + #ifdef WITH_AUDIT +@@ -471,12 +474,15 @@ static char *new_pw_passwd (char *pw_pas + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); +- s = pw_pass; +- while ('\0' != *s) { +- *s = *(s + 1); +- s++; +- } ++ memmove (pw_pass, s, strlen (s) + 1); + } else if (pflg) { ++ if (strchr (user_pass, ':') != NULL) { ++ fprintf (stderr, ++ _("%s: The password field cannot contain a colon character.\n"), ++ Prog); ++ return NULL; ++ ++ } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, + "updating-password", +@@ -525,6 +531,8 @@ static void new_pwent (struct passwd *pw + if ( (!is_shadow_pwd) + || (strcmp (pwent->pw_passwd, SHADOW_PASSWD_STRING) != 0)) { + pwent->pw_passwd = new_pw_passwd (pwent->pw_passwd); ++ if (pwent->pw_passwd == NULL) ++ fail_exit (E_PW_UPDATE); + } + + if (uflg) { +@@ -639,6 +647,8 @@ static void new_spent (struct spwd *spen + * + aging has been requested + */ + spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp); ++ if (spent->sp_pwdp == NULL) ++ fail_exit(E_PW_UPDATE); + + if (pflg) { + spent->sp_lstchg = (long) gettime () / SCALE; diff --git a/SOURCES/shadow-4.6-audit-update.patch b/SOURCES/shadow-4.6-audit-update.patch new file mode 100644 index 0000000..b9d0a67 --- /dev/null +++ b/SOURCES/shadow-4.6-audit-update.patch @@ -0,0 +1,2347 @@ +diff -up shadow-4.6/libmisc/audit_help.c.audit-update shadow-4.6/libmisc/audit_help.c +--- shadow-4.6/libmisc/audit_help.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/libmisc/audit_help.c 2018-05-28 15:01:09.913717564 +0200 +@@ -68,7 +68,7 @@ void audit_help_open (void) + * This function will log a message to the audit system using a predefined + * message format. Parameter usage is as follows: + * +- * type - type of message: AUDIT_USER_CHAUTHTOK for changing any account ++ * type - type of message: AUDIT_USER_MGMT for changing any account + * attributes. + * pgname - program's name + * op - operation. "adding user", "changing finger info", "deleting group" +@@ -88,6 +88,39 @@ void audit_logger (int type, unused cons + } + } + ++/* ++ * This function will log a message to the audit system using a predefined ++ * message format. Parameter usage is as follows: ++ * ++ * type - type of message: AUDIT_USER_MGMT for changing any account ++ * attributes. ++ * pgname - program's name ++ * op - operation. "adding user", "changing finger info", "deleting group" ++ * name - user's account or group name. If not available use NULL. ++ * id - uid or gid that the operation is being performed on. This is used ++ * only when user is NULL. ++ * grp - group name associated with event ++ */ ++void audit_logger_with_group (int type, unused const char *pgname, ++ const char *op, const char *name, unsigned int id, ++ const char *grp, shadow_audit_result result) ++{ ++ int len; ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1], buf[1024]; ++ if (audit_fd < 0) { ++ return; ++ } ++ len = strnlen(grp, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(grp, len)) { ++ snprintf(buf, sizeof(buf), "%s grp=%s", op, ++ audit_encode_value(enc_group, grp, len)); ++ } else { ++ snprintf(buf, sizeof(buf), "%s grp=\"%s\"", op, grp); ++ } ++ audit_log_acct_message (audit_fd, type, NULL, buf, name, id, ++ NULL, NULL, NULL, (int) result); ++} ++ + void audit_logger_message (const char *message, shadow_audit_result result) + { + if (audit_fd < 0) { +diff -up shadow-4.6/libmisc/cleanup_group.c.audit-update shadow-4.6/libmisc/cleanup_group.c +--- shadow-4.6/libmisc/cleanup_group.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/libmisc/cleanup_group.c 2018-05-28 15:01:09.913717564 +0200 +@@ -83,7 +83,7 @@ void cleanup_report_mod_group (void *cle + gr_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -101,7 +101,7 @@ void cleanup_report_mod_gshadow (void *c + sgr_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -122,7 +122,7 @@ void cleanup_report_add_group_group (voi + SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/group", ++ "adding-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -141,8 +141,8 @@ void cleanup_report_add_group_gshadow (v + + SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "adding-shadow-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -164,8 +164,8 @@ void cleanup_report_del_group_group (voi + "failed to remove group %s from %s", + name, gr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "removing group from /etc/group", ++ audit_logger (AUDIT_DEL_GROUP, Prog, ++ "removing-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -187,8 +187,8 @@ void cleanup_report_del_group_gshadow (v + "failed to remove group %s from %s", + name, sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "removing group from /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "removing-shadow-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -208,7 +208,7 @@ void cleanup_unlock_group (unused void * + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking group file", ++ audit_logger_message ("unlocking-group", + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -228,7 +228,7 @@ void cleanup_unlock_gshadow (unused void + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking gshadow file", ++ audit_logger_message ("unlocking-gshadow", + SHADOW_AUDIT_FAILURE); + #endif + } +diff -up shadow-4.6/libmisc/cleanup_user.c.audit-update shadow-4.6/libmisc/cleanup_user.c +--- shadow-4.6/libmisc/cleanup_user.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/libmisc/cleanup_user.c 2018-05-28 15:01:09.913717564 +0200 +@@ -65,7 +65,7 @@ void cleanup_report_mod_passwd (void *cl + pw_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_USER_MGMT, Prog, + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -86,7 +86,7 @@ void cleanup_report_add_user_passwd (voi + SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to /etc/passwd", ++ "adding-user", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -105,8 +105,8 @@ void cleanup_report_add_user_shadow (voi + + SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to /etc/shadow", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "adding-shadow-user", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -125,7 +125,7 @@ void cleanup_unlock_passwd (unused void + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking passwd file", ++ audit_logger_message ("unlocking-passwd", + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -144,7 +144,7 @@ void cleanup_unlock_shadow (unused void + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking shadow file", ++ audit_logger_message ("unlocking-shadow", + SHADOW_AUDIT_FAILURE); + #endif + } +diff -up shadow-4.6/lib/prototypes.h.audit-update shadow-4.6/lib/prototypes.h +--- shadow-4.6/lib/prototypes.h.audit-update 2018-05-28 15:01:09.901717309 +0200 ++++ shadow-4.6/lib/prototypes.h 2018-05-28 15:01:09.913717564 +0200 +@@ -211,12 +211,21 @@ extern int audit_fd; + extern void audit_help_open (void); + /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ + #define AUDIT_NO_ID ((unsigned int) -1) ++#ifndef AUDIT_GRP_MGMT ++#define AUDIT_GRP_MGMT 1132 /* Group account was modified */ ++#endif ++#ifndef AUDIT_GRP_CHAUTHTOK ++#define AUDIT_GRP_CHAUTHTOK 1133 /* Group account password was changed */ ++#endif + typedef enum { + SHADOW_AUDIT_FAILURE = 0, + SHADOW_AUDIT_SUCCESS = 1} shadow_audit_result; + extern void audit_logger (int type, const char *pgname, const char *op, + const char *name, unsigned int id, + shadow_audit_result result); ++void audit_logger_with_group (int type, unused const char *pgname, ++ const char *op, const char *name, unsigned int id, ++ const char *grp, shadow_audit_result result); + void audit_logger_message (const char *message, shadow_audit_result result); + #endif + +diff -up shadow-4.6/src/gpasswd.c.audit-update shadow-4.6/src/gpasswd.c +--- shadow-4.6/src/gpasswd.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/gpasswd.c 2018-05-28 15:01:09.914717585 +0200 +@@ -137,7 +137,7 @@ static void usage (int status) + (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); + (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); + (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); +- (void) fputs (_(" -r, --remove-password remove the GROUP's password\n"), usageout); ++ (void) fputs (_(" -r, --delete-password remove the GROUP's password\n"), usageout); + (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); + (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); + #ifdef SHADOWGRP +@@ -396,21 +396,14 @@ static void open_files (void) + + static void log_gpasswd_failure (const char *suffix) + { +-#ifdef WITH_AUDIT +- char buf[1024]; +-#endif + if (aflg) { + SYSLOG ((LOG_ERR, + "%s failed to add user %s to group %s%s", + myname, user, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to add user %s to group %s%s", +- myname, user, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (dflg) { +@@ -418,13 +411,9 @@ static void log_gpasswd_failure (const c + "%s failed to remove user %s from group %s%s", + myname, user, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to remove user %s from group %s%s", +- myname, user, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (rflg) { +@@ -432,13 +421,9 @@ static void log_gpasswd_failure (const c + "%s failed to remove password of group %s%s", + myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to remove password of group %s%s", +- myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "delete-group-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (Rflg) { +@@ -446,13 +431,9 @@ static void log_gpasswd_failure (const c + "%s failed to restrict access to group %s%s", + myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to restrict access to group %s%s", +- myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "restrict-group", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (Aflg || Mflg) { +@@ -462,13 +443,9 @@ static void log_gpasswd_failure (const c + "%s failed to set the administrators of group %s to %s%s", + myname, group, admins, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to set the administrators of group %s to %s%s", +- myname, group, admins, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "set-admins-of-group", ++ admins, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -478,13 +455,9 @@ static void log_gpasswd_failure (const c + "%s failed to set the members of group %s to %s%s", + myname, group, members, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to set the members of group %s to %s%s", +- myname, group, members, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-users-to-group", ++ members, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -493,13 +466,9 @@ static void log_gpasswd_failure (const c + "%s failed to change password of group %s%s", + myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to change password of group %s%s", +- myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "change-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -530,21 +499,14 @@ static void log_gpasswd_failure_gshadow + + static void log_gpasswd_success (const char *suffix) + { +-#ifdef WITH_AUDIT +- char buf[1024]; +-#endif + if (aflg) { + SYSLOG ((LOG_INFO, + "user %s added by %s to group %s%s", + user, myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "user %s added by %s to group %s%s", +- user, myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (dflg) { +@@ -552,13 +514,9 @@ static void log_gpasswd_success (const c + "user %s removed by %s from group %s%s", + user, myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "user %s removed by %s from group %s%s", +- user, myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (rflg) { +@@ -566,13 +524,9 @@ static void log_gpasswd_success (const c + "password of group %s removed by %s%s", + group, myname, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "password of group %s removed by %s%s", +- group, myname, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "delete-group-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (Rflg) { +@@ -580,13 +534,9 @@ static void log_gpasswd_success (const c + "access to group %s restricted by %s%s", + group, myname, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "access to group %s restricted by %s%s", +- group, myname, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "restrict-group", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (Aflg || Mflg) { +@@ -596,13 +546,9 @@ static void log_gpasswd_success (const c + "administrators of group %s set by %s to %s%s", + group, myname, admins, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "administrators of group %s set by %s to %s%s", +- group, myname, admins, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "set-admins-of-group", ++ admins, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } +@@ -612,13 +558,9 @@ static void log_gpasswd_success (const c + "members of group %s set by %s to %s%s", + group, myname, members, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "members of group %s set by %s to %s%s", +- group, myname, members, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-users-to-group", ++ members, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } +@@ -627,13 +569,9 @@ static void log_gpasswd_success (const c + "password of group %s changed by %s%s", + group, myname, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "password of group %s changed by %s%s", +- group, myname, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "change-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } +diff -up shadow-4.6/src/groupadd.c.audit-update shadow-4.6/src/groupadd.c +--- shadow-4.6/src/groupadd.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/groupadd.c 2018-05-28 15:02:53.137910337 +0200 +@@ -130,6 +130,15 @@ static /*@noreturn@*/void usage (int sta + exit (status); + } + ++static void fail_exit(int status) ++{ ++#ifdef WITH_AUDIT ++ audit_logger(AUDIT_ADD_GROUP, Prog, "add-group", group_name, ++ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); ++#endif ++ exit (status); ++} ++ + /* + * new_grent - initialize the values in a group file entry + * +@@ -213,7 +222,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), grp.gr_name); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef SHADOWGRP + /* +@@ -223,7 +232,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), sgrp.sg_name); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #endif /* SHADOWGRP */ + } +@@ -247,7 +256,7 @@ static void check_new_name (void) + fprintf (stderr, _("%s: '%s' is not a valid group name\n"), + Prog, group_name); + +- exit (E_BAD_ARG); ++ fail_exit (E_BAD_ARG); + } + + /* +@@ -263,11 +272,11 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/group", ++ "add-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -285,11 +294,11 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "add-shadow-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -303,12 +312,6 @@ static void close_files (void) + #endif /* SHADOWGRP */ + + /* Report success at the system level */ +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "", +- group_name, (unsigned int) group_id, +- SHADOW_AUDIT_SUCCESS); +-#endif + SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", + group_name, (unsigned int) group_id)); + del_cleanup (cleanup_report_add_group); +@@ -326,7 +329,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_group, NULL); + +@@ -336,7 +339,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_gshadow, NULL); + } +@@ -352,7 +355,7 @@ static void open_files (void) + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef SHADOWGRP +@@ -362,7 +365,7 @@ static void open_files (void) + _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + } + #endif /* SHADOWGRP */ +@@ -495,7 +498,7 @@ static void check_flags (void) + fprintf (stderr, + _("%s: group '%s' already exists\n"), + Prog, group_name); +- exit (E_NAME_IN_USE); ++ fail_exit (E_NAME_IN_USE); + } + + if (gflg && (prefix_getgrgid (group_id) != NULL)) { +@@ -514,7 +517,7 @@ static void check_flags (void) + fprintf (stderr, + _("%s: GID '%lu' already exists\n"), + Prog, (unsigned long int) group_id); +- exit (E_GID_IN_USE); ++ fail_exit (E_GID_IN_USE); + } + } + } +@@ -542,7 +545,7 @@ static void check_perms (void) + fprintf (stderr, + _("%s: Cannot determine your user name.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); +@@ -562,7 +565,7 @@ static void check_perms (void) + if (NULL != pamh) { + (void) pam_end (pamh, retval); + } +- exit (1); ++ fail_exit (1); + } + (void) pam_end (pamh, retval); + #endif /* USE_PAM */ +@@ -595,7 +598,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot setup cleanup service.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + /* +@@ -617,7 +620,7 @@ int main (int argc, char **argv) + + if (!gflg) { + if (find_new_gid (rflg, &group_id, NULL) < 0) { +- exit (E_GID_IN_USE); ++ fail_exit (E_GID_IN_USE); + } + } + +diff -up shadow-4.6/src/groupdel.c.audit-update shadow-4.6/src/groupdel.c +--- shadow-4.6/src/groupdel.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/groupdel.c 2018-05-28 15:01:09.914717585 +0200 +@@ -105,6 +105,15 @@ static /*@noreturn@*/void usage (int sta + exit (status); + } + ++static void fail_exit(int status) ++{ ++#ifdef WITH_AUDIT ++ audit_logger(AUDIT_GRP_MGMT, Prog, "delete-group", group_name, ++ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); ++#endif ++ exit (status); ++} ++ + /* + * grp_update - update group file entries + * +@@ -131,7 +140,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, group_name, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef SHADOWGRP +@@ -143,7 +152,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, group_name, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + } + #endif /* SHADOWGRP */ +@@ -162,12 +171,12 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_GROUP, Prog, +- "removing group from /etc/group", ++ "delete-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -187,12 +196,12 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "removing group from /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "delete-shadow-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -206,13 +215,6 @@ static void close_files (void) + } + #endif /* SHADOWGRP */ + +- /* Report success at the system level */ +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "", +- group_name, (unsigned int) group_id, +- SHADOW_AUDIT_SUCCESS); +-#endif + SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); + del_cleanup (cleanup_report_del_group); + } +@@ -229,7 +231,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_group, NULL); + #ifdef SHADOWGRP +@@ -238,7 +240,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_gshadow, NULL); + } +@@ -256,7 +258,7 @@ static void open_files (void) + _("%s: cannot open %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef SHADOWGRP + if (is_shadow_grp) { +@@ -265,7 +267,7 @@ static void open_files (void) + _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + } + #endif /* SHADOWGRP */ +@@ -306,7 +308,7 @@ static void group_busy (gid_t gid) + fprintf (stderr, + _("%s: cannot remove the primary group of user '%s'\n"), + Prog, pwd->pw_name); +- exit (E_GROUP_BUSY); ++ fail_exit (E_GROUP_BUSY); + } + + /* +@@ -391,7 +393,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot setup cleanup service.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + process_flags (argc, argv); +@@ -405,7 +407,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot determine your user name.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh); +@@ -426,7 +428,7 @@ int main (int argc, char **argv) + if (NULL != pamh) { + (void) pam_end (pamh, retval); + } +- exit (1); ++ fail_exit (1); + } + (void) pam_end (pamh, retval); + #endif /* USE_PAM */ +@@ -446,7 +448,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: group '%s' does not exist\n"), + Prog, group_name); +- exit (E_NOTFOUND); ++ fail_exit (E_NOTFOUND); + } + + group_id = grp->gr_gid; +@@ -470,7 +472,7 @@ int main (int argc, char **argv) + _("%s: %s is the NIS master\n"), + Prog, nis_master); + } +- exit (E_NOTFOUND); ++ fail_exit (E_NOTFOUND); + } + #endif + +diff -up shadow-4.6/src/groupmod.c.audit-update shadow-4.6/src/groupmod.c +--- shadow-4.6/src/groupmod.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/groupmod.c 2018-05-28 15:01:09.915717607 +0200 +@@ -449,7 +449,7 @@ static void close_files (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info_group.audit_msg, + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); +@@ -472,7 +472,7 @@ static void close_files (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info_gshadow.audit_msg, + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); +@@ -495,7 +495,7 @@ static void close_files (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info_passwd.audit_msg, + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); +@@ -510,8 +510,8 @@ static void close_files (void) + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, +- "modifying group", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "modify-group", + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -523,6 +523,8 @@ static void close_files (void) + */ + static void prepare_failure_reports (void) + { ++ char *nv_pair, nv[64]; ++ + info_group.name = group_name; + #ifdef SHADOWGRP + info_gshadow.name = group_name; +@@ -535,76 +537,106 @@ static void prepare_failure_reports (voi + #endif + info_passwd.audit_msg = xmalloc (512); + +- (void) snprintf (info_group.audit_msg, 511, +- "changing %s; ", gr_dbname ()); ++ info_group.action = xmalloc (512); + #ifdef SHADOWGRP +- (void) snprintf (info_gshadow.audit_msg, 511, +- "changing %s; ", sgr_dbname ()); ++ info_gshadow.action = xmalloc (512); + #endif +- (void) snprintf (info_passwd.audit_msg, 511, +- "changing %s; ", pw_dbname ()); ++ info_passwd.action = xmalloc (512); + +- info_group.action = info_group.audit_msg +- + strlen (info_group.audit_msg); ++ (void) snprintf (info_group.audit_msg, 511, ++ "changing-group"); + #ifdef SHADOWGRP +- info_gshadow.action = info_gshadow.audit_msg +- + strlen (info_gshadow.audit_msg); ++ (void) snprintf (info_gshadow.audit_msg, 511, ++ "changing-shadow-group"); + #endif +- info_passwd.action = info_passwd.audit_msg +- + strlen (info_passwd.audit_msg); ++ (void) snprintf (info_passwd.audit_msg, 511, ++ "changing-group-passwd"); + ++ nv_pair = audit_encode_nv_string(" grp", group_name, ++ strlen(group_name)); ++ if(nv_pair) { ++ strncat(info_group.audit_msg, nv_pair, ++ 511 - strlen(info_group.audit_msg)); ++#ifdef SHADOWGRP ++ strncat(info_gshadow.audit_msg, nv_pair, ++ 511 - strlen(info_gshadow.audit_msg)); ++#endif ++ strncat(info_passwd.audit_msg, nv_pair, ++ 511 - strlen(info_passwd.audit_msg)); ++ free(nv_pair); ++ } ++ snprintf(nv, sizeof(nv), " gid=%lu", (unsigned long)group_id); ++ strncat(info_group.audit_msg, nv, 511 - strlen(info_group.audit_msg)); ++ strncat(info_passwd.audit_msg, nv, 511 - strlen(info_passwd.audit_msg)); ++ + (void) snprintf (info_group.action, +- 511 - strlen (info_group.audit_msg), ++ 511, + "group %s/%lu", + group_name, (unsigned long int) group_id); + #ifdef SHADOWGRP + (void) snprintf (info_gshadow.action, +- 511 - strlen (info_group.audit_msg), ++ 511, + "group %s", group_name); + #endif + (void) snprintf (info_passwd.action, +- 511 - strlen (info_group.audit_msg), ++ 511, + "group %s/%lu", + group_name, (unsigned long int) group_id); + + if (nflg) { ++ nv_pair = audit_encode_nv_string(" new_group", group_newname, ++ strlen(group_newname)); ++ strncat(info_group.audit_msg, nv_pair, ++ 511 - strlen(info_group.audit_msg)); + strncat (info_group.action, ", new name: ", +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + strncat (info_group.action, group_newname, +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + + #ifdef SHADOWGRP ++ strncat(info_gshadow.audit_msg, nv_pair, ++ 511 - strlen(info_gshadow.audit_msg)); + strncat (info_gshadow.action, ", new name: ", +- 511 - strlen (info_gshadow.audit_msg)); ++ 511 - strlen (info_gshadow.action)); + strncat (info_gshadow.action, group_newname, +- 511 - strlen (info_gshadow.audit_msg)); ++ 511 - strlen (info_gshadow.action)); + #endif + ++ strncat(info_passwd.audit_msg, nv_pair, ++ 511 - strlen(info_passwd.audit_msg)); + strncat (info_passwd.action, ", new name: ", +- 511 - strlen (info_passwd.audit_msg)); ++ 511 - strlen (info_passwd.action)); + strncat (info_passwd.action, group_newname, +- 511 - strlen (info_passwd.audit_msg)); ++ 511 - strlen (info_passwd.action)); ++ free(nv_pair); + } + if (pflg) { ++ /* Note: audit doesn't want this value recorded */ + strncat (info_group.action, ", new password", +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + + #ifdef SHADOWGRP + strncat (info_gshadow.action, ", new password", +- 511 - strlen (info_gshadow.audit_msg)); ++ 511 - strlen (info_gshadow.action)); + #endif + } + if (gflg) { ++ snprintf(nv, sizeof(nv), " new_gid=%lu", (unsigned long)group_newid); ++ strncat(info_group.audit_msg, nv, ++ 511 - strlen(info_group.audit_msg)); ++ strncat(info_passwd.audit_msg, nv, ++ 511 - strlen(info_passwd.audit_msg)); ++ + strncat (info_group.action, ", new gid: ", +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + (void) snprintf (info_group.action+strlen (info_group.action), +- 511 - strlen (info_group.audit_msg), ++ 511 - strlen (info_group.action), + "%lu", (unsigned long int) group_newid); + + strncat (info_passwd.action, ", new gid: ", +- 511 - strlen (info_passwd.audit_msg)); ++ 511 - strlen (info_passwd.action)); + (void) snprintf (info_passwd.action+strlen (info_passwd.action), +- 511 - strlen (info_passwd.audit_msg), ++ 511 - strlen (info_passwd.action), + "%lu", (unsigned long int) group_newid); + } + info_group.audit_msg[511] = '\0'; +@@ -612,6 +644,11 @@ static void prepare_failure_reports (voi + info_gshadow.audit_msg[511] = '\0'; + #endif + info_passwd.audit_msg[511] = '\0'; ++ info_group.action[511] = '\0'; ++#ifdef SHADOWGRP ++ info_gshadow.action[511] = '\0'; ++#endif ++ info_passwd.action[511] = '\0'; + + // FIXME: add a system cleanup + add_cleanup (cleanup_report_mod_group, &info_group); +diff -up shadow-4.6/src/chage.c.audit-update shadow-4.6/src/chage.c +--- shadow-4.6/src/chage.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/chage.c 2018-05-28 15:01:09.915717607 +0200 +@@ -126,9 +126,10 @@ static /*@noreturn@*/void fail_exit (int + + #ifdef WITH_AUDIT + if (E_SUCCESS != code) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change age", +- user_name, (unsigned int) user_uid, 0); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-age", ++ user_name, (unsigned int) user_uid, ++ SHADOW_AUDIT_FAILURE); + } + #endif + +@@ -873,11 +874,7 @@ int main (int argc, char **argv) + fprintf (stderr, _("%s: Permission denied.\n"), Prog); + fail_exit (E_NOPERM); + } +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "display aging info", +- user_name, (unsigned int) user_uid, 1); +-#endif ++ /* Displaying fields is not of interest to audit */ + list_fields (); + fail_exit (E_SUCCESS); + } +@@ -896,41 +893,43 @@ int main (int argc, char **argv) + } + #ifdef WITH_AUDIT + else { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change all aging information", +- user_name, (unsigned int) user_uid, 1); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-all-aging-information", ++ user_name, (unsigned int) user_uid, ++ SHADOW_AUDIT_SUCCESS); + } + #endif + } else { + #ifdef WITH_AUDIT + if (Mflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change max age", +- user_name, (unsigned int) user_uid, 1); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-max-age", ++ user_name, (unsigned int) user_uid, ++ SHADOW_AUDIT_SUCCESS); + } + if (mflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change min age", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-min-age", + user_name, (unsigned int) user_uid, 1); + } + if (dflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change last change date", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-last-change-date", + user_name, (unsigned int) user_uid, 1); + } + if (Wflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change passwd warning", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-passwd-warning", + user_name, (unsigned int) user_uid, 1); + } + if (Iflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change inactive days", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-inactive-days", + user_name, (unsigned int) user_uid, 1); + } + if (Eflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change passwd expiration", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-passwd-expiration", + user_name, (unsigned int) user_uid, 1); + } + #endif +diff -up shadow-4.6/src/newgrp.c.audit-update shadow-4.6/src/newgrp.c +--- shadow-4.6/src/newgrp.c.audit-update 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/newgrp.c 2018-05-28 15:01:09.915717607 +0200 +@@ -206,11 +206,12 @@ static void check_perms (const struct gr + strcmp (cpasswd, grp->gr_passwd) != 0) { + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "authentication new-gid=%lu", ++ "authentication new_gid=%lu", + (unsigned long) grp->gr_gid); + audit_logger (AUDIT_GRP_AUTH, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + #endif + SYSLOG ((LOG_INFO, + "Invalid password for group '%s' from '%s'", +@@ -221,11 +222,12 @@ static void check_perms (const struct gr + } + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "authentication new-gid=%lu", ++ "authentication new_gid=%lu", + (unsigned long) grp->gr_gid); + audit_logger (AUDIT_GRP_AUTH, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 1); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_SUCCESS); + #endif + } + +@@ -236,19 +238,6 @@ failure: + * harm. -- JWP + */ + closelog (); +-#ifdef WITH_AUDIT +- if (groupname) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", groupname); +- audit_logger (AUDIT_CHGRP_ID, Prog, +- audit_buf, NULL, +- (unsigned int) getuid (), 0); +- } else { +- audit_logger (AUDIT_CHGRP_ID, Prog, +- "changing", NULL, +- (unsigned int) getuid (), 0); +- } +-#endif + exit (EXIT_FAILURE); + } + +@@ -320,15 +309,27 @@ static void syslog_sg (const char *name, + is_newgrp ? "newgrp" : "sg", strerror (errno)); + #ifdef WITH_AUDIT + if (group) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", group); ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; ++ int len = strnlen(group, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(group, len)) { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=%s", ++ audit_encode_value(enc_group, ++ group, len)); ++ } else { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=\"%s\"", ++ group); ++ } + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } else { + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } + #endif + exit (EXIT_FAILURE); +@@ -457,7 +458,7 @@ int main (int argc, char **argv) + #ifdef WITH_AUDIT + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", + (unsigned long) getuid ())); +@@ -573,15 +574,26 @@ int main (int argc, char **argv) + perror ("getgroups"); + #ifdef WITH_AUDIT + if (group) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", group); ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; ++ int len = strnlen(group, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(group, len)) { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=%s", ++ audit_encode_value(enc_group, ++ group, len)); ++ } else { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=\"%s\"", group); ++ } + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } else { + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } + #endif + exit (EXIT_FAILURE); +@@ -738,10 +750,10 @@ int main (int argc, char **argv) + perror ("setgid"); + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "changing new-gid=%lu", (unsigned long) gid); ++ "changing new_gid=%lu", (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + exit (EXIT_FAILURE); + } +@@ -750,10 +762,10 @@ int main (int argc, char **argv) + perror ("setuid"); + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "changing new-gid=%lu", (unsigned long) gid); ++ "changing new_gid=%lu", (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + exit (EXIT_FAILURE); + } +@@ -767,10 +779,10 @@ int main (int argc, char **argv) + execl (SHELL, "sh", "-c", command, (char *) 0); + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "changing new-gid=%lu", (unsigned long) gid); ++ "changing new_gid=%lu", (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + perror (SHELL); + exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); +@@ -834,11 +846,11 @@ int main (int argc, char **argv) + } + + #ifdef WITH_AUDIT +- snprintf (audit_buf, sizeof(audit_buf), "changing new-gid=%lu", ++ snprintf (audit_buf, sizeof(audit_buf), "changing new_gid=%lu", + (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 1); ++ (unsigned int) getuid (), SHADOW_AUDIT_SUCCESS); + #endif + /* + * Exec the login shell and go away. We are trying to get back to +@@ -862,15 +874,24 @@ int main (int argc, char **argv) + closelog (); + #ifdef WITH_AUDIT + if (NULL != group) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", group); ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; ++ int len = strnlen(group, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(group, len)) { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=%s", ++ audit_encode_value(enc_group, ++ group, len)); ++ } else { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=\"%s\"", group); ++ } + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + } else { + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + } + #endif + exit (EXIT_FAILURE); +diff -up shadow-4.6/src/useradd.c.audit-update shadow-4.6/src/useradd.c +--- shadow-4.6/src/useradd.c.audit-update 2018-05-28 15:01:09.903717352 +0200 ++++ shadow-4.6/src/useradd.c 2018-05-28 15:06:36.824662074 +0200 +@@ -229,6 +229,8 @@ static void create_mail (void); + */ + static void fail_exit (int code) + { ++ int type; ++ + if (home_added) { + if (rmdir (prefix_user_home) != 0) { + fprintf (stderr, +@@ -242,12 +244,6 @@ static void fail_exit (int code) + if (spw_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking shadow file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -255,12 +251,6 @@ static void fail_exit (int code) + if (pw_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking passwd file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -268,12 +258,6 @@ static void fail_exit (int code) + if (gr_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking group file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -282,12 +266,6 @@ static void fail_exit (int code) + if (sgr_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking gshadow file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -297,12 +275,6 @@ static void fail_exit (int code) + if (sub_uid_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking subordinate user file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -310,20 +282,19 @@ static void fail_exit (int code) + if (sub_gid_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking subordinate group file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } + #endif /* ENABLE_SUBIDS */ + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", ++ if (code == E_PW_UPDATE || code >= E_GRP_UPDATE) ++ type = AUDIT_USER_MGMT; ++ else ++ type = AUDIT_ADD_USER; ++ ++ audit_logger (type, Prog, ++ "add-user", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -673,7 +644,7 @@ static int set_defaults (void) + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USYS_CONFIG, Prog, +- "changing useradd defaults", ++ "changing-useradd-defaults", + NULL, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -950,12 +921,6 @@ static void grp_update (void) + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_GRP_UPDATE); /* XXX */ + } + +@@ -969,18 +934,12 @@ static void grp_update (void) + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), ngrp->gr_name); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user_name, AUDIT_NO_ID, ngrp->gr_name, + SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, +@@ -1025,12 +984,6 @@ static void grp_update (void) + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to shadow group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_GRP_UPDATE); /* XXX */ + } + +@@ -1044,18 +997,13 @@ static void grp_update (void) + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), nsgrp->sg_name); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to shadow group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif ++ + fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to shadow group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-to-shadow-group", ++ user_name, AUDIT_NO_ID, nsgrp->sg_name, + SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, +@@ -1407,7 +1355,7 @@ static void process_flags (int argc, cha + Prog, user_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", ++ "add-user", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1522,7 +1470,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking shadow file", ++ "unlocking-shadow-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1535,7 +1483,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking passwd file", ++ "unlocking-passwd-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1547,7 +1495,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking group file", ++ "unlocking-group-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1561,7 +1509,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking gshadow file", ++ "unlocking-gshadow-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1577,7 +1525,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking subordinate user file", ++ "unlocking-subordinate-user-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1591,7 +1539,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking subordinate group file", ++ "unlocking-subordinate-group-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1783,7 +1731,7 @@ static void grp_add (void) + Prog, gr_dbname (), grp.gr_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group", ++ "add-group", + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1799,7 +1747,7 @@ static void grp_add (void) + Prog, sgr_dbname (), sgrp.sg_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group", ++ "add-group", + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1809,7 +1757,7 @@ static void grp_add (void) + SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group", ++ "add-group", + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -1970,12 +1918,6 @@ static void usr_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), spent.sp_namp); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding shadow password", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_PW_UPDATE); + } + #ifdef ENABLE_SUBIDS +@@ -1997,7 +1939,7 @@ static void usr_update (void) + + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", ++ "add-user", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -2032,12 +1974,6 @@ static void create_home (void) + fprintf (stderr, + _("%s: cannot create directory %s\n"), + Prog, prefix_user_home); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding home directory", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_HOMEDIR); + } + (void) chown (prefix_user_home, user_id, user_gid); +@@ -2045,8 +1981,8 @@ static void create_home (void) + 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK)); + home_added = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "add-home-dir", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -2231,12 +2167,6 @@ int main (int argc, char **argv) + */ + if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ + fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_NAME_IN_USE); + } + +@@ -2252,12 +2182,6 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), + Prog, user_name); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_NAME_IN_USE); + } + } +@@ -2287,12 +2211,6 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: UID %lu is not unique\n"), + Prog, (unsigned long) user_id); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_UID_IN_USE); + } + } +@@ -2365,9 +2283,10 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), + Prog, user_name, user_selinux); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding SELinux user mapping", +- user_name, (unsigned int) user_id, 0); ++ audit_logger (AUDIT_ROLE_ASSIGN, Prog, ++ "add-selinux-user-mapping", ++ user_name, (unsigned int) user_id, ++ SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ + rv = E_SE_UPDATE; + } +diff -up shadow-4.6/src/userdel.c.audit-update shadow-4.6/src/userdel.c +--- shadow-4.6/src/userdel.c.audit-update 2018-05-28 15:01:09.909717479 +0200 ++++ shadow-4.6/src/userdel.c 2018-05-28 15:01:09.916717628 +0200 +@@ -219,9 +219,9 @@ static void update_groups (void) + * Update the DBM group file with the new entry as well. + */ + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user from group", +- user_name, (unsigned int) user_id, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "deleting-user-from-group", ++ user_name, (unsigned int) user_id, ngrp->gr_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", +@@ -281,9 +281,9 @@ static void update_groups (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user from shadow group", +- user_name, (unsigned int) user_id, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "deleting-user-from-shadow-group", ++ user_name, (unsigned int) user_id, nsgrp->sg_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", +@@ -360,9 +360,9 @@ static void remove_usergroup (void) + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "deleting group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_DEL_GROUP, Prog, ++ "delete-group", ++ user_name, AUDIT_NO_ID, user_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, +@@ -378,9 +378,9 @@ static void remove_usergroup (void) + fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "deleting shadow group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "delete-shadow-group", ++ user_name, AUDIT_NO_ID, user_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, +@@ -542,7 +542,7 @@ static void fail_exit (int code) + + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user", ++ "delete-user", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -562,24 +562,12 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, pw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + if (is_shadow_pwd) { +@@ -587,12 +575,6 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking shadow password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + spw_locked = true; +@@ -600,12 +582,6 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening shadow password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + } +@@ -613,23 +589,11 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + #ifdef SHADOWGRP +@@ -638,24 +602,12 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking shadow group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + sgr_locked= true; + if (sgr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening shadow group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + } +@@ -666,24 +618,12 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_uid_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking subordinate user file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_SUB_UID_UPDATE); + } + sub_uid_locked = true; + if (sub_uid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening subordinate user file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_SUB_UID_UPDATE); + } + } +@@ -692,24 +632,12 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_gid_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking subordinate group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_SUB_GID_UPDATE); + } + sub_gid_locked = true; + if (sub_gid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening subordinate group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_SUB_GID_UPDATE); + } + } +@@ -754,7 +682,7 @@ static void update_user (void) + #endif /* ENABLE_SUBIDS */ + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user entries", ++ "delete-user", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ +@@ -862,7 +790,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -879,7 +807,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -889,8 +817,8 @@ static int remove_mailbox (void) + #ifdef WITH_AUDIT + else + { +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + } +@@ -908,7 +836,7 @@ static int remove_mailbox (void) + mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -925,7 +853,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -935,8 +863,8 @@ static int remove_mailbox (void) + #ifdef WITH_AUDIT + else + { +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + } +@@ -1149,7 +1077,7 @@ int main (int argc, char **argv) + Prog, user_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user not found", ++ "deleting-user-not-found", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -1205,7 +1133,7 @@ int main (int argc, char **argv) + if (!fflg) { + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user logged in", ++ "deleting-user-logged-in", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -1282,8 +1210,8 @@ int main (int argc, char **argv) + #ifdef WITH_AUDIT + else + { +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "deleting-home-directory", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + } +@@ -1292,7 +1220,7 @@ int main (int argc, char **argv) + #ifdef WITH_AUDIT + if (0 != errors) { + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting home directory", ++ "deleting-home-directory", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + } +@@ -1305,8 +1233,8 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), + Prog, user_name); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "removing SELinux user mapping", ++ audit_logger (AUDIT_ROLE_REMOVE, Prog, ++ "delete-selinux-user-mapping", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +diff -up shadow-4.6/src/usermod.c.audit-update shadow-4.6/src/usermod.c +--- shadow-4.6/src/usermod.c.audit-update 2018-05-28 15:01:09.912717543 +0200 ++++ shadow-4.6/src/usermod.c 2018-05-28 15:08:25.424969050 +0200 +@@ -453,8 +453,8 @@ static char *new_pw_passwd (char *pw_pas + + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "updating passwd", +- user_newname, (unsigned int) user_newid, 0); ++ "updating-password", ++ user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); + strcpy (buf, "!"); +@@ -473,8 +473,8 @@ static char *new_pw_passwd (char *pw_pas + + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "updating password", +- user_newname, (unsigned int) user_newid, 0); ++ "updating-password", ++ user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); + s = pw_pass; +@@ -485,7 +485,7 @@ static char *new_pw_passwd (char *pw_pas + } else if (pflg) { + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing password", ++ "updating-password", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); +@@ -514,8 +514,8 @@ static void new_pwent (struct passwd *pw + fail_exit (E_NAME_IN_USE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing name", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-name", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -535,8 +535,8 @@ static void new_pwent (struct passwd *pw + + if (uflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing uid", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-uid", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -546,8 +546,8 @@ static void new_pwent (struct passwd *pw + } + if (gflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing primary group", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-primary-group", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -557,8 +557,8 @@ static void new_pwent (struct passwd *pw + } + if (cflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing comment", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-comment", + user_newname, (unsigned int) user_newid, 1); + #endif + pwent->pw_gecos = user_newcomment; +@@ -566,8 +566,8 @@ static void new_pwent (struct passwd *pw + + if (dflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-home-dir", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -577,8 +577,8 @@ static void new_pwent (struct passwd *pw + } + if (sflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing user shell", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-shell", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -608,8 +608,8 @@ static void new_spent (struct spwd *spen + + if (fflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing inactive days", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-inactive-days", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -625,8 +625,8 @@ static void new_spent (struct spwd *spen + date_to_str (old_exp, sizeof(old_exp), + user_expire * DAY); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing expiration date", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-expiration-date", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -709,9 +709,9 @@ static /*@noreturn@*/void fail_exit (int + #endif /* ENABLE_SUBIDS */ + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "modifying account", +- user_name, AUDIT_NO_ID, 0); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "modify-account", ++ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); + #endif + exit (code); + } +@@ -765,9 +765,12 @@ static void update_group (void) + user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing group member", +- user_newname, AUDIT_NO_ID, 1); ++ audit_logger_with_group ( ++ AUDIT_USER_MGMT, Prog, ++ "update-member-in-group", ++ user_newname, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "change '%s' to '%s' in group '%s'", +@@ -781,9 +784,11 @@ static void update_group (void) + ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "removing group member", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user_name, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "delete '%s' from group '%s'", +@@ -796,9 +801,11 @@ static void update_group (void) + ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user_name, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, "add '%s' to group '%s'", + user_newname, ngrp->gr_name)); +@@ -873,9 +880,10 @@ static void update_gshadow (void) + nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing admin name in shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "update-admin-name-in-shadow-group", ++ user_name, AUDIT_NO_ID, nsgrp->sg_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "change admin '%s' to '%s' in shadow group '%s'", +@@ -895,9 +903,10 @@ static void update_gshadow (void) + user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing member in shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "update-member-in-shadow-group", ++ user_name, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, + "change '%s' to '%s' in shadow group '%s'", +@@ -911,9 +920,10 @@ static void update_gshadow (void) + nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "removing user from shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-shadow-group", ++ user_name, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, + "delete '%s' from shadow group '%s'", +@@ -926,9 +936,10 @@ static void update_gshadow (void) + nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to shadow group", +- user_newname, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-shadow-group", ++ user_newname, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", + user_newname, nsgrp->sg_name)); +@@ -1789,8 +1800,8 @@ static void move_home (void) + + #ifdef WITH_AUDIT + if (uflg || gflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing home directory owner", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-home-dir-owner", + user_newname, (unsigned int) user_newid, 1); + } + #endif +@@ -1808,8 +1819,8 @@ static void move_home (void) + fail_exit (E_HOMEDIR); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "moving home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "moving-home-dir", + user_newname, (unsigned int) user_newid, + 1); + #endif +@@ -1828,9 +1839,9 @@ static void move_home (void) + Prog, prefix_user_home); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, ++ audit_logger (AUDIT_USER_MGMT, + Prog, +- "moving home directory", ++ "moving-home-dir", + user_newname, + (unsigned int) user_newid, + 1); +@@ -2045,8 +2056,8 @@ static void move_mailbox (void) + } + #ifdef WITH_AUDIT + else { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing mail file owner", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-mail-file-owner", + user_newname, (unsigned int) user_newid, 1); + } + #endif +@@ -2072,8 +2083,8 @@ static void move_mailbox (void) + } + #ifdef WITH_AUDIT + else { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing mail file name", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-mail-file-name", + user_newname, (unsigned int) user_newid, 1); + } + #endif +@@ -2267,8 +2278,8 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), + Prog, user_name, user_selinux); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "modifying User mapping ", ++ audit_logger (AUDIT_ROLE_ASSIGN, Prog, ++ "changing-selinux-user-mapping ", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -2280,8 +2291,8 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), + Prog, user_name); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "removing SELinux user mapping", ++ audit_logger (AUDIT_ROLE_REMOVE, Prog, ++ "delete-selinux-user-mapping", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -2319,8 +2330,8 @@ int main (int argc, char **argv) + */ + #ifdef WITH_AUDIT + if (uflg || gflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing home directory owner", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-home-dir-owner", + user_newname, (unsigned int) user_newid, 1); + } + #endif diff --git a/SOURCES/shadow-4.6-chgrp-guard.patch b/SOURCES/shadow-4.6-chgrp-guard.patch new file mode 100644 index 0000000..2918684 --- /dev/null +++ b/SOURCES/shadow-4.6-chgrp-guard.patch @@ -0,0 +1,44 @@ +diff -up shadow-4.6/man/usermod.8.xml.chgrp-guard shadow-4.6/man/usermod.8.xml +--- shadow-4.6/man/usermod.8.xml.chgrp-guard 2018-11-06 09:08:54.170095358 +0100 ++++ shadow-4.6/man/usermod.8.xml 2018-12-18 15:24:12.283181180 +0100 +@@ -195,6 +195,12 @@ + The group ownership of files outside of the user's home directory + must be fixed manually. + ++ ++ The change of the group ownership of files inside of the user's ++ home directory is also not done if the home dir owner uid is ++ different from the current or new user id. This is safety measure ++ for special home directories such as /. ++ + + + +@@ -372,6 +378,12 @@ + must be fixed manually. + + ++ The change of the user ownership of files inside of the user's ++ home directory is also not done if the home dir owner uid is ++ different from the current or new user id. This is safety measure ++ for special home directories such as /. ++ ++ + No checks will be performed with regard to the + , , + , or +diff -up shadow-4.6/src/usermod.c.chgrp-guard shadow-4.6/src/usermod.c +--- shadow-4.6/src/usermod.c.chgrp-guard 2018-12-18 15:24:12.286181249 +0100 ++++ shadow-4.6/src/usermod.c 2018-12-18 15:26:51.227841435 +0100 +@@ -2336,7 +2336,10 @@ int main (int argc, char **argv) + } + + if (!mflg && (uflg || gflg)) { +- if (access (dflg ? prefix_user_newhome : prefix_user_home, F_OK) == 0) { ++ struct stat sb; ++ ++ if (stat (dflg ? prefix_user_newhome : prefix_user_home, &sb) == 0 && ++ ((uflg && sb.st_uid == user_newid) || sb.st_uid == user_id)) { + /* + * Change the UID on all of the files owned by + * `user_id' to `user_newid' in the user's home diff --git a/SOURCES/shadow-4.6-coverity.patch b/SOURCES/shadow-4.6-coverity.patch new file mode 100644 index 0000000..44533e2 --- /dev/null +++ b/SOURCES/shadow-4.6-coverity.patch @@ -0,0 +1,223 @@ +diff -up shadow-4.6/lib/commonio.c.coverity shadow-4.6/lib/commonio.c +--- shadow-4.6/lib/commonio.c.coverity 2018-10-10 09:50:59.307738194 +0200 ++++ shadow-4.6/lib/commonio.c 2018-10-10 09:55:32.919319048 +0200 +@@ -382,7 +382,7 @@ int commonio_lock_nowait (struct commoni + char* lock = NULL; + size_t lock_file_len; + size_t file_len; +- int err; ++ int err = 0; + + if (db->locked) { + return 1; +@@ -391,12 +391,10 @@ int commonio_lock_nowait (struct commoni + lock_file_len = strlen(db->filename) + 6; /* sizeof ".lock" */ + file = (char*)malloc(file_len); + if(file == NULL) { +- err = ENOMEM; + goto cleanup_ENOMEM; + } + lock = (char*)malloc(lock_file_len); + if(lock == NULL) { +- err = ENOMEM; + goto cleanup_ENOMEM; + } + snprintf (file, file_len, "%s.%lu", +diff -up shadow-4.6/libmisc/console.c.coverity shadow-4.6/libmisc/console.c +--- shadow-4.6/libmisc/console.c.coverity 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/libmisc/console.c 2018-10-10 11:56:51.368837533 +0200 +@@ -50,7 +50,7 @@ static bool is_listed (const char *cfgin + static bool is_listed (const char *cfgin, const char *tty, bool def) + { + FILE *fp; +- char buf[200], *s; ++ char buf[1024], *s; + const char *cons; + + /* +@@ -70,7 +70,8 @@ static bool is_listed (const char *cfgin + + if (*cons != '/') { + char *pbuf; +- strcpy (buf, cons); ++ strncpy (buf, cons, sizeof (buf)); ++ buf[sizeof (buf) - 1] = '\0'; + pbuf = &buf[0]; + while ((s = strtok (pbuf, ":")) != NULL) { + if (strcmp (s, tty) == 0) { +diff -up shadow-4.6/lib/spawn.c.coverity shadow-4.6/lib/spawn.c +--- shadow-4.6/lib/spawn.c.coverity 2018-04-29 18:42:37.000000001 +0200 ++++ shadow-4.6/lib/spawn.c 2018-10-10 11:36:49.035784609 +0200 +@@ -69,7 +69,7 @@ int run_command (const char *cmd, const + do { + wpid = waitpid (pid, status, 0); + } while ( ((pid_t)-1 == wpid && errno == EINTR) +- || (wpid != pid)); ++ || ((pid_t)-1 != wpid && wpid != pid)); + + if ((pid_t)-1 == wpid) { + fprintf (stderr, "%s: waitpid (status: %d): %s\n", +diff -up shadow-4.6/src/useradd.c.coverity shadow-4.6/src/useradd.c +--- shadow-4.6/src/useradd.c.coverity 2018-10-10 09:50:59.303738098 +0200 ++++ shadow-4.6/src/useradd.c 2018-10-12 13:51:54.480490257 +0200 +@@ -314,7 +314,7 @@ static void fail_exit (int code) + static void get_defaults (void) + { + FILE *fp; +- char* default_file = USER_DEFAULTS_FILE; ++ char *default_file = USER_DEFAULTS_FILE; + char buf[1024]; + char *cp; + +@@ -324,6 +324,8 @@ static void get_defaults (void) + + len = strlen(prefix) + strlen(USER_DEFAULTS_FILE) + 2; + default_file = malloc(len); ++ if (default_file == NULL) ++ return; + wlen = snprintf(default_file, len, "%s/%s", prefix, USER_DEFAULTS_FILE); + assert (wlen == (int) len -1); + } +@@ -334,7 +336,7 @@ static void get_defaults (void) + + fp = fopen (default_file, "r"); + if (NULL == fp) { +- return; ++ goto getdef_err; + } + + /* +@@ -445,7 +447,7 @@ static void get_defaults (void) + } + } + (void) fclose (fp); +- ++ getdef_err: + if(prefix[0]) { + free(default_file); + } +@@ -480,8 +482,8 @@ static int set_defaults (void) + FILE *ifp; + FILE *ofp; + char buf[1024]; +- char* new_file = NEW_USER_FILE; +- char* default_file = USER_DEFAULTS_FILE; ++ char *new_file = NULL; ++ char *default_file = USER_DEFAULTS_FILE; + char *cp; + int ofd; + int wlen; +@@ -492,17 +494,30 @@ static int set_defaults (void) + bool out_shell = false; + bool out_skel = false; + bool out_create_mail_spool = false; ++ size_t len; ++ int ret = -1; + +- if(prefix[0]) { +- size_t len; + +- len = strlen(prefix) + strlen(NEW_USER_FILE) + 2; +- new_file = malloc(len); +- wlen = snprintf(new_file, len, "%s/%s", prefix, NEW_USER_FILE); +- assert (wlen == (int) len -1); ++ len = strlen(prefix) + strlen(NEW_USER_FILE) + 2; ++ new_file = malloc(len); ++ if (new_file == NULL) { ++ fprintf (stderr, ++ _("%s: cannot create new defaults file: %s\n"), ++ Prog, strerror(errno)); ++ return -1; ++ } ++ wlen = snprintf(new_file, len, "%s%s%s", prefix, prefix[0]?"/":"", NEW_USER_FILE); ++ assert (wlen <= (int) len -1); + ++ if(prefix[0]) { + len = strlen(prefix) + strlen(USER_DEFAULTS_FILE) + 2; + default_file = malloc(len); ++ if (default_file == NULL) { ++ fprintf (stderr, ++ _("%s: cannot create new defaults file: %s\n"), ++ Prog, strerror(errno)); ++ goto setdef_err; ++ } + wlen = snprintf(default_file, len, "%s/%s", prefix, USER_DEFAULTS_FILE); + assert (wlen == (int) len -1); + } +@@ -515,7 +530,7 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: cannot create new defaults file\n"), + Prog); +- return -1; ++ goto setdef_err; + } + + ofp = fdopen (ofd, "w"); +@@ -523,7 +538,7 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: cannot open new defaults file\n"), + Prog); +- return -1; ++ goto setdef_err; + } + + /* +@@ -550,7 +565,7 @@ static int set_defaults (void) + _("%s: line too long in %s: %s..."), + Prog, default_file, buf); + (void) fclose (ifp); +- return -1; ++ goto setdef_err; + } + } + +@@ -614,7 +629,7 @@ static int set_defaults (void) + || (fsync (fileno (ofp)) != 0) + || (fclose (ofp) != 0)) { + unlink (new_file); +- return -1; ++ goto setdef_err; + } + + /* +@@ -629,7 +644,7 @@ static int set_defaults (void) + _("%s: Cannot create backup file (%s): %s\n"), + Prog, buf, strerror (err)); + unlink (new_file); +- return -1; ++ goto setdef_err; + } + + /* +@@ -640,11 +655,11 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: rename: %s: %s\n"), + Prog, new_file, strerror (err)); +- return -1; ++ goto setdef_err; + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USYS_CONFIG, Prog, +- "changing-useradd-defaults", ++ "changing useradd defaults", + NULL, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -654,13 +669,14 @@ static int set_defaults (void) + (unsigned int) def_group, def_home, def_shell, + def_inactive, def_expire, def_template, + def_create_mail_spool)); +- ++ ret = 0; ++ setdef_err: ++ free(new_file); + if(prefix[0]) { +- free(new_file); + free(default_file); + } + +- return 0; ++ return ret; + } + + /* diff --git a/SOURCES/shadow-4.6-getenforce.patch b/SOURCES/shadow-4.6-getenforce.patch new file mode 100644 index 0000000..8a55bf5 --- /dev/null +++ b/SOURCES/shadow-4.6-getenforce.patch @@ -0,0 +1,21 @@ +diff -up shadow-4.6/lib/selinux.c.getenforce shadow-4.6/lib/selinux.c +--- shadow-4.6/lib/selinux.c.getenforce 2018-05-28 15:10:15.870315221 +0200 ++++ shadow-4.6/lib/selinux.c 2018-05-28 15:10:15.894315731 +0200 +@@ -75,7 +75,7 @@ int set_selinux_file_context (const char + } + return 0; + error: +- if (security_getenforce () != 0) { ++ if (security_getenforce () > 0) { + return 1; + } + return 0; +@@ -95,7 +95,7 @@ int reset_selinux_file_context (void) + selinux_checked = true; + } + if (selinux_enabled) { +- if (setfscreatecon (NULL) != 0) { ++ if (setfscreatecon (NULL) != 0 && security_getenforce () > 0) { + return 1; + } + } diff --git a/SOURCES/shadow-4.6-ignore-login-prompt.patch b/SOURCES/shadow-4.6-ignore-login-prompt.patch new file mode 100644 index 0000000..faf50f7 --- /dev/null +++ b/SOURCES/shadow-4.6-ignore-login-prompt.patch @@ -0,0 +1,11 @@ +diff -up shadow-4.6/lib/getdef.c.login-prompt shadow-4.6/lib/getdef.c +--- shadow-4.6/lib/getdef.c.login-prompt 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/lib/getdef.c 2019-03-21 15:06:58.009280504 +0100 +@@ -94,6 +94,7 @@ static struct itemdef def_table[] = { + {"KILLCHAR", NULL}, + {"LOGIN_RETRIES", NULL}, + {"LOGIN_TIMEOUT", NULL}, ++ {"LOGIN_PLAIN_PROMPT", NULL}, + {"LOG_OK_LOGINS", NULL}, + {"LOG_UNKFAIL_ENAB", NULL}, + {"MAIL_DIR", NULL}, diff --git a/SOURCES/shadow-4.6-move-home.patch b/SOURCES/shadow-4.6-move-home.patch new file mode 100644 index 0000000..cff9561 --- /dev/null +++ b/SOURCES/shadow-4.6-move-home.patch @@ -0,0 +1,15 @@ +diff -up shadow-4.6/src/usermod.c.move-home shadow-4.6/src/usermod.c +--- shadow-4.6/src/usermod.c.move-home 2018-05-28 14:59:05.594076665 +0200 ++++ shadow-4.6/src/usermod.c 2018-05-28 15:00:28.479837392 +0200 +@@ -1845,6 +1845,11 @@ static void move_home (void) + Prog, prefix_user_home, prefix_user_newhome); + fail_exit (E_HOMEDIR); + } ++ } else { ++ fprintf (stderr, ++ _("%s: The previous home directory (%s) does " ++ "not exist or is inaccessible. Move cannot be completed.\n"), ++ Prog, prefix_user_home); + } + } + diff --git a/SOURCES/shadow-4.6-orig-context.patch b/SOURCES/shadow-4.6-orig-context.patch new file mode 100644 index 0000000..ea522e7 --- /dev/null +++ b/SOURCES/shadow-4.6-orig-context.patch @@ -0,0 +1,128 @@ +diff -up shadow-4.6/lib/commonio.c.orig-context shadow-4.6/lib/commonio.c +--- shadow-4.6/lib/commonio.c.orig-context 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/lib/commonio.c 2018-05-28 14:56:37.287929667 +0200 +@@ -961,7 +961,7 @@ int commonio_close (struct commonio_db * + snprintf (buf, sizeof buf, "%s-", db->filename); + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (buf) != 0) { ++ if (set_selinux_file_context (buf, db->filename) != 0) { + errors++; + } + #endif +@@ -994,7 +994,7 @@ int commonio_close (struct commonio_db * + snprintf (buf, sizeof buf, "%s+", db->filename); + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (buf) != 0) { ++ if (set_selinux_file_context (buf, db->filename) != 0) { + errors++; + } + #endif +diff -up shadow-4.6/libmisc/copydir.c.orig-context shadow-4.6/libmisc/copydir.c +--- shadow-4.6/libmisc/copydir.c.orig-context 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/libmisc/copydir.c 2018-05-28 14:56:37.287929667 +0200 +@@ -484,7 +484,7 @@ static int copy_dir (const char *src, co + */ + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (dst) != 0) { ++ if (set_selinux_file_context (dst, NULL) != 0) { + return -1; + } + #endif /* WITH_SELINUX */ +@@ -605,7 +605,7 @@ static int copy_symlink (const char *src + } + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (dst) != 0) { ++ if (set_selinux_file_context (dst, NULL) != 0) { + free (oldlink); + return -1; + } +@@ -684,7 +684,7 @@ static int copy_special (const char *src + int err = 0; + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (dst) != 0) { ++ if (set_selinux_file_context (dst, NULL) != 0) { + return -1; + } + #endif /* WITH_SELINUX */ +@@ -744,7 +744,7 @@ static int copy_file (const char *src, c + return -1; + } + #ifdef WITH_SELINUX +- if (set_selinux_file_context (dst) != 0) { ++ if (set_selinux_file_context (dst, NULL) != 0) { + return -1; + } + #endif /* WITH_SELINUX */ +diff -up shadow-4.6/lib/prototypes.h.orig-context shadow-4.6/lib/prototypes.h +--- shadow-4.6/lib/prototypes.h.orig-context 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/lib/prototypes.h 2018-05-28 14:56:37.287929667 +0200 +@@ -326,7 +326,7 @@ extern /*@observer@*/const char *crypt_m + + /* selinux.c */ + #ifdef WITH_SELINUX +-extern int set_selinux_file_context (const char *dst_name); ++extern int set_selinux_file_context (const char *dst_name, const char *orig_name); + extern int reset_selinux_file_context (void); + #endif + +diff -up shadow-4.6/lib/selinux.c.orig-context shadow-4.6/lib/selinux.c +--- shadow-4.6/lib/selinux.c.orig-context 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/lib/selinux.c 2018-05-28 14:56:37.287929667 +0200 +@@ -50,7 +50,7 @@ static bool selinux_enabled; + * Callers may have to Reset SELinux to create files with default + * contexts with reset_selinux_file_context + */ +-int set_selinux_file_context (const char *dst_name) ++int set_selinux_file_context (const char *dst_name, const char *orig_name) + { + /*@null@*/security_context_t scontext = NULL; + +@@ -62,19 +62,23 @@ int set_selinux_file_context (const char + if (selinux_enabled) { + /* Get the default security context for this file */ + if (matchpathcon (dst_name, 0, &scontext) < 0) { +- if (security_getenforce () != 0) { +- return 1; +- } ++ /* We could not get the default, copy the original */ ++ if (orig_name == NULL) ++ goto error; ++ if (getfilecon (orig_name, &scontext) < 0) ++ goto error; + } + /* Set the security context for the next created file */ +- if (setfscreatecon (scontext) < 0) { +- if (security_getenforce () != 0) { +- return 1; +- } +- } ++ if (setfscreatecon (scontext) < 0) ++ goto error; + freecon (scontext); + } + return 0; ++ error: ++ if (security_getenforce () != 0) { ++ return 1; ++ } ++ return 0; + } + + /* +diff -up shadow-4.6/src/useradd.c.orig-context shadow-4.6/src/useradd.c +--- shadow-4.6/src/useradd.c.orig-context 2018-05-28 14:56:37.288929688 +0200 ++++ shadow-4.6/src/useradd.c 2018-05-28 14:58:02.242730903 +0200 +@@ -2020,7 +2020,7 @@ static void create_home (void) + { + if (access (prefix_user_home, F_OK) != 0) { + #ifdef WITH_SELINUX +- if (set_selinux_file_context (prefix_user_home) != 0) { ++ if (set_selinux_file_context (prefix_user_home, NULL) != 0) { + fprintf (stderr, + _("%s: cannot set SELinux context for home directory %s\n"), + Prog, user_home); diff --git a/SOURCES/shadow-4.6-redhat.patch b/SOURCES/shadow-4.6-redhat.patch new file mode 100644 index 0000000..7a8be2e --- /dev/null +++ b/SOURCES/shadow-4.6-redhat.patch @@ -0,0 +1,41 @@ +diff -up shadow-4.6/src/useradd.c.redhat shadow-4.6/src/useradd.c +--- shadow-4.6/src/useradd.c.redhat 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/src/useradd.c 2018-05-28 13:37:16.695651258 +0200 +@@ -98,7 +98,7 @@ const char *Prog; + static gid_t def_group = 100; + static const char *def_gname = "other"; + static const char *def_home = "/home"; +-static const char *def_shell = ""; ++static const char *def_shell = "/sbin/nologin"; + static const char *def_template = SKEL_DIR; + static const char *def_create_mail_spool = "no"; + +@@ -108,7 +108,7 @@ static const char *def_expire = ""; + #define VALID(s) (strcspn (s, ":\n") == strlen (s)) + + static const char *user_name = ""; +-static const char *user_pass = "!"; ++static const char *user_pass = "!!"; + static uid_t user_id; + static gid_t user_gid; + static const char *user_comment = ""; +@@ -1114,9 +1114,9 @@ static void process_flags (int argc, cha + }; + while ((c = getopt_long (argc, argv, + #ifdef WITH_SELINUX +- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:UZ:", ++ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:P:s:u:UZ:", + #else /* !WITH_SELINUX */ +- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U", ++ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:P:s:u:U", + #endif /* !WITH_SELINUX */ + long_options, NULL)) != -1) { + switch (c) { +@@ -1267,6 +1267,7 @@ static void process_flags (int argc, cha + case 'M': + Mflg = true; + break; ++ case 'n': + case 'N': + Nflg = true; + break; diff --git a/SOURCES/shadow-4.6-selinux.patch b/SOURCES/shadow-4.6-selinux.patch new file mode 100644 index 0000000..dfd5140 --- /dev/null +++ b/SOURCES/shadow-4.6-selinux.patch @@ -0,0 +1,115 @@ +diff -up shadow-4.6/lib/semanage.c.selinux shadow-4.6/lib/semanage.c +--- shadow-4.6/lib/semanage.c.selinux 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/lib/semanage.c 2018-05-28 13:38:20.551008911 +0200 +@@ -294,6 +294,9 @@ int set_seuser (const char *login_name, + + ret = 0; + ++ /* drop obsolete matchpathcon cache */ ++ matchpathcon_fini(); ++ + done: + semanage_seuser_key_free (key); + semanage_handle_destroy (handle); +@@ -369,6 +372,10 @@ int del_seuser (const char *login_name) + } + + ret = 0; ++ ++ /* drop obsolete matchpathcon cache */ ++ matchpathcon_fini(); ++ + done: + semanage_handle_destroy (handle); + return ret; +diff -up shadow-4.6/src/useradd.c.selinux shadow-4.6/src/useradd.c +--- shadow-4.6/src/useradd.c.selinux 2018-05-28 13:43:30.996748997 +0200 ++++ shadow-4.6/src/useradd.c 2018-05-28 13:44:04.645486199 +0200 +@@ -2120,6 +2120,7 @@ static void create_mail (void) + */ + int main (int argc, char **argv) + { ++ int rv = E_SUCCESS; + #ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + pam_handle_t *pamh = NULL; +@@ -2342,27 +2343,11 @@ int main (int argc, char **argv) + + usr_update (); + +- if (mflg) { +- create_home (); +- if (home_added) { +- copy_tree (def_template, prefix_user_home, false, false, +- (uid_t)-1, user_id, (gid_t)-1, user_gid); +- } else { +- fprintf (stderr, +- _("%s: warning: the home directory already exists.\n" +- "Not copying any file from skel directory into it.\n"), +- Prog); +- } +- +- } +- +- /* Do not create mail directory for system accounts */ +- if (!rflg) { +- create_mail (); +- } +- + close_files (); + ++ nscd_flush_cache ("passwd"); ++ nscd_flush_cache ("group"); ++ + /* + * tallylog_reset needs to be able to lookup + * a valid existing user name, +@@ -2373,8 +2358,9 @@ int main (int argc, char **argv) + } + + #ifdef WITH_SELINUX +- if (Zflg) { +- if (set_seuser (user_name, user_selinux) != 0) { ++ if (Zflg && *user_selinux) { ++ if (is_selinux_enabled () > 0) { ++ if (set_seuser (user_name, user_selinux) != 0) { + fprintf (stderr, + _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), + Prog, user_name, user_selinux); +@@ -2383,14 +2369,31 @@ int main (int argc, char **argv) + "adding SELinux user mapping", + user_name, (unsigned int) user_id, 0); + #endif /* WITH_AUDIT */ +- fail_exit (E_SE_UPDATE); ++ rv = E_SE_UPDATE; ++ } + } + } +-#endif /* WITH_SELINUX */ ++#endif + +- nscd_flush_cache ("passwd"); +- nscd_flush_cache ("group"); ++ if (mflg) { ++ create_home (); ++ if (home_added) { ++ copy_tree (def_template, prefix_user_home, false, true, ++ (uid_t)-1, user_id, (gid_t)-1, user_gid); ++ } else { ++ fprintf (stderr, ++ _("%s: warning: the home directory already exists.\n" ++ "Not copying any file from skel directory into it.\n"), ++ Prog); ++ } ++ ++ } ++ ++ /* Do not create mail directory for system accounts */ ++ if (!rflg) { ++ create_mail (); ++ } + +- return E_SUCCESS; ++ return rv; + } + diff --git a/SOURCES/shadow-4.6-sysugid-min-limit.patch b/SOURCES/shadow-4.6-sysugid-min-limit.patch new file mode 100644 index 0000000..4cea6ef --- /dev/null +++ b/SOURCES/shadow-4.6-sysugid-min-limit.patch @@ -0,0 +1,34 @@ +diff -up shadow-4.6/libmisc/find_new_gid.c.min-limit shadow-4.6/libmisc/find_new_gid.c +--- shadow-4.6/libmisc/find_new_gid.c.min-limit 2018-04-29 18:42:37.000000001 +0200 ++++ shadow-4.6/libmisc/find_new_gid.c 2018-11-06 10:51:20.554963292 +0100 +@@ -82,6 +82,13 @@ static int get_ranges (bool sys_group, g + (unsigned long) *max_id); + return EINVAL; + } ++ /* ++ * Zero is reserved for root and the allocation algorithm does not ++ * work right with it. ++ */ ++ if (*min_id == 0) { ++ *min_id = (gid_t) 1; ++ } + } else { + /* Non-system groups */ + +diff -up shadow-4.6/libmisc/find_new_uid.c.min-limit shadow-4.6/libmisc/find_new_uid.c +--- shadow-4.6/libmisc/find_new_uid.c.min-limit 2018-04-29 18:42:37.000000001 +0200 ++++ shadow-4.6/libmisc/find_new_uid.c 2018-11-06 10:51:39.341399569 +0100 +@@ -82,6 +82,13 @@ static int get_ranges (bool sys_user, ui + (unsigned long) *max_id); + return EINVAL; + } ++ /* ++ * Zero is reserved for root and the allocation algorithm does not ++ * work right with it. ++ */ ++ if (*min_id == 0) { ++ *min_id = (uid_t) 1; ++ } + } else { + /* Non-system users */ + diff --git a/SOURCES/shadow-4.6-use-itstool.patch b/SOURCES/shadow-4.6-use-itstool.patch new file mode 100644 index 0000000..760b5b3 --- /dev/null +++ b/SOURCES/shadow-4.6-use-itstool.patch @@ -0,0 +1,31 @@ +diff -up shadow-4.6/man/generate_translations.mak.use-itstool shadow-4.6/man/generate_translations.mak +--- shadow-4.6/man/generate_translations.mak.use-itstool 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/man/generate_translations.mak 2018-07-31 16:42:21.623990969 +0200 +@@ -5,8 +5,19 @@ config.xml: ../config.xml.in + $(MAKE) -C .. config.xml + cp ../config.xml $@ + +-%.xml: ../%.xml ../po/$(LANG).po +- xml2po --expand-all-entities -l $(LANG) -p ../po/$(LANG).po -o $@ ../$@ ++messages.mo: ../po/$(LANG).po ++ msgfmt ../po/$(LANG).po -o messages.mo ++ ++login.defs.d: ++ ln -sf ../login.defs.d login.defs.d ++ ++%.xml: ../%.xml messages.mo login.defs.d ++ if grep -q SHADOW-CONFIG-HERE $< ; then \ ++ sed -e 's/^/%config;/' $< > $@; \ ++ else \ ++ sed -e 's/^\(/\1 [%config;]>/' $< > $@; \ ++ fi ++ itstool -d -l $(LANG) -m messages.mo -o . $@ + sed -i 's:\(^:\1 lang="$(LANG)">:' $@ + + include ../generate_mans.mak +@@ -16,4 +27,4 @@ $(man_MANS): + @echo you need to run configure with --enable-man to generate man pages + endif + +-CLEANFILES = .xml2po.mo $(EXTRA_DIST) $(addsuffix .xml,$(EXTRA_DIST)) config.xml ++CLEANFILES = messages.mo login.defs.d $(EXTRA_DIST) $(addsuffix .xml,$(EXTRA_DIST)) config.xml diff --git a/SOURCES/shadow-4.6-use-lckpwdf.patch b/SOURCES/shadow-4.6-use-lckpwdf.patch new file mode 100644 index 0000000..363579a --- /dev/null +++ b/SOURCES/shadow-4.6-use-lckpwdf.patch @@ -0,0 +1,190 @@ +commit 408b8a548243aebaa6d773beeae8ddf4bb6100f0 +Author: Tomas Mraz +Date: Thu May 2 14:33:06 2019 +0200 + + Use the lckpwdf() again if prefix is not set + + The implementation of prefix option dropped the use of lckpwdf(). + However that is incorrect as other tools manipulating the shadow passwords + such as PAM use lckpwdf() and do not know anything about the + shadow's own locking mechanism. + + This reverts the implementation to use lckpwdf() if prefix option + is not used. + +diff --git a/lib/commonio.c b/lib/commonio.c +index 26e518f2..94dda779 100644 +--- a/lib/commonio.c ++++ b/lib/commonio.c +@@ -364,6 +364,7 @@ static void free_linked_list (struct commonio_db *db) + int commonio_setname (struct commonio_db *db, const char *name) + { + snprintf (db->filename, sizeof (db->filename), "%s", name); ++ db->setname = true; + return 1; + } + +@@ -414,37 +415,39 @@ cleanup_ENOMEM: + + int commonio_lock (struct commonio_db *db) + { +-/*#ifdef HAVE_LCKPWDF*/ /* not compatible with prefix option*/ +-#if 0 +- /* +- * only if the system libc has a real lckpwdf() - the one from +- * lockpw.c calls us and would cause infinite recursion! +- */ ++ int i; + ++#ifdef HAVE_LCKPWDF + /* +- * Call lckpwdf() on the first lock. +- * If it succeeds, call *_lock() only once +- * (no retries, it should always succeed). ++ * Only if the system libc has a real lckpwdf() - the one from ++ * lockpw.c calls us and would cause infinite recursion! ++ * It is also not used with the prefix option. + */ +- if (0 == lock_count) { +- if (lckpwdf () == -1) { +- if (geteuid () != 0) { +- (void) fprintf (stderr, +- "%s: Permission denied.\n", +- Prog); ++ if (!db->setname) { ++ /* ++ * Call lckpwdf() on the first lock. ++ * If it succeeds, call *_lock() only once ++ * (no retries, it should always succeed). ++ */ ++ if (0 == lock_count) { ++ if (lckpwdf () == -1) { ++ if (geteuid () != 0) { ++ (void) fprintf (stderr, ++ "%s: Permission denied.\n", ++ Prog); ++ } ++ return 0; /* failure */ + } +- return 0; /* failure */ + } +- } + +- if (commonio_lock_nowait (db, true) != 0) { +- return 1; /* success */ +- } ++ if (commonio_lock_nowait (db, true) != 0) { ++ return 1; /* success */ ++ } + +- ulckpwdf (); +- return 0; /* failure */ +-#else /* !HAVE_LCKPWDF */ +- int i; ++ ulckpwdf (); ++ return 0; /* failure */ ++ } ++#endif /* !HAVE_LCKPWDF */ + + /* + * lckpwdf() not used - do it the old way. +@@ -471,7 +474,6 @@ int commonio_lock (struct commonio_db *db) + } + } + return 0; /* failure */ +-#endif /* !HAVE_LCKPWDF */ + } + + static void dec_lock_count (void) +diff --git a/lib/commonio.h b/lib/commonio.h +index 40e5708f..64e83073 100644 +--- a/lib/commonio.h ++++ b/lib/commonio.h +@@ -143,6 +143,7 @@ struct commonio_db { + bool isopen:1; + bool locked:1; + bool readonly:1; ++ bool setname:1; + }; + + extern int commonio_setname (struct commonio_db *, const char *); +diff --git a/lib/groupio.c b/lib/groupio.c +index ae2302b5..bffb06e0 100644 +--- a/lib/groupio.c ++++ b/lib/groupio.c +@@ -139,7 +139,8 @@ static /*@owned@*/struct commonio_db group_db = { + false, /* changed */ + false, /* isopen */ + false, /* locked */ +- false /* readonly */ ++ false, /* readonly */ ++ false /* setname */ + }; + + int gr_setdbname (const char *filename) +diff --git a/lib/pwio.c b/lib/pwio.c +index 7ee85377..127719cb 100644 +--- a/lib/pwio.c ++++ b/lib/pwio.c +@@ -114,7 +114,8 @@ static struct commonio_db passwd_db = { + false, /* changed */ + false, /* isopen */ + false, /* locked */ +- false /* readonly */ ++ false, /* readonly */ ++ false /* setname */ + }; + + int pw_setdbname (const char *filename) +diff --git a/lib/sgroupio.c b/lib/sgroupio.c +index 5423626a..ffbdb263 100644 +--- a/lib/sgroupio.c ++++ b/lib/sgroupio.c +@@ -238,7 +238,8 @@ static struct commonio_db gshadow_db = { + false, /* changed */ + false, /* isopen */ + false, /* locked */ +- false /* readonly */ ++ false, /* readonly */ ++ false /* setname */ + }; + + int sgr_setdbname (const char *filename) +diff --git a/lib/shadowio.c b/lib/shadowio.c +index 5fa3d312..676b1f1a 100644 +--- a/lib/shadowio.c ++++ b/lib/shadowio.c +@@ -114,7 +114,8 @@ static struct commonio_db shadow_db = { + false, /* changed */ + false, /* isopen */ + false, /* locked */ +- false /* readonly */ ++ false, /* readonly */ ++ false /* setname */ + }; + + int spw_setdbname (const char *filename) +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index a662e67e..dd779c59 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -550,7 +550,8 @@ static struct commonio_db subordinate_uid_db = { + false, /* changed */ + false, /* isopen */ + false, /* locked */ +- false /* readonly */ ++ false, /* readonly */ ++ false /* setname */ + }; + + int sub_uid_setdbname (const char *filename) +@@ -631,7 +632,8 @@ static struct commonio_db subordinate_gid_db = { + false, /* changed */ + false, /* isopen */ + false, /* locked */ +- false /* readonly */ ++ false, /* readonly */ ++ false /* setname */ + }; + + int sub_gid_setdbname (const char *filename) diff --git a/SOURCES/shadow-4.6-usermod-crash.patch b/SOURCES/shadow-4.6-usermod-crash.patch new file mode 100644 index 0000000..d2861b3 --- /dev/null +++ b/SOURCES/shadow-4.6-usermod-crash.patch @@ -0,0 +1,42 @@ +diff -up shadow-4.6/libmisc/prefix_flag.c.usermod-crash shadow-4.6/libmisc/prefix_flag.c +--- shadow-4.6/libmisc/prefix_flag.c.usermod-crash 2018-04-29 18:42:37.000000000 +0200 ++++ shadow-4.6/libmisc/prefix_flag.c 2018-05-28 15:14:10.642302440 +0200 +@@ -319,6 +319,7 @@ extern struct group *prefix_getgr_nam_gi + { + long long int gid; + char *endptr; ++ struct group *g; + + if (NULL == grname) { + return NULL; +@@ -333,7 +334,8 @@ extern struct group *prefix_getgr_nam_gi + && (gid == (gid_t)gid)) { + return prefix_getgrgid ((gid_t) gid); + } +- return prefix_getgrnam (grname); ++ g = prefix_getgrnam (grname); ++ return g ? __gr_dup(g) : NULL; + } + else + return getgr_nam_gid(grname); +diff -up shadow-4.6/src/usermod.c.usermod-crash shadow-4.6/src/usermod.c +--- shadow-4.6/src/usermod.c.usermod-crash 2018-05-28 15:12:37.920332763 +0200 ++++ shadow-4.6/src/usermod.c 2018-05-28 15:15:50.337422470 +0200 +@@ -1276,11 +1276,13 @@ static void process_flags (int argc, cha + prefix_user_home = xmalloc(len); + wlen = snprintf(prefix_user_home, len, "%s/%s", prefix, user_home); + assert (wlen == (int) len -1); ++ if (user_newhome) { ++ len = strlen(prefix) + strlen(user_newhome) + 2; ++ prefix_user_newhome = xmalloc(len); ++ wlen = snprintf(prefix_user_newhome, len, "%s/%s", prefix, user_newhome); ++ assert (wlen == (int) len -1); ++ } + +- len = strlen(prefix) + strlen(user_newhome) + 2; +- prefix_user_newhome = xmalloc(len); +- wlen = snprintf(prefix_user_newhome, len, "%s/%s", prefix, user_newhome); +- assert (wlen == (int) len -1); + } + else { + prefix_user_home = user_home; diff --git a/SOURCES/shadow-4.6.tar.xz.asc b/SOURCES/shadow-4.6.tar.xz.asc new file mode 100644 index 0000000..e36c97f --- /dev/null +++ b/SOURCES/shadow-4.6.tar.xz.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQEzBAABCgAdFiEE8dCNt3gYW/eEAC3/6f7qBqheP50FAlrncOkACgkQ6f7qBqhe +P52UGAf/eOnoIYIZ52y72iMxeNfQMTMjYTZd1YrtjlK0RQKquK7FrCOg91MvOF2B +hLVKu2OU7mzuPTMSAraAxjXLkrM0E3vFjMtu1fHBGlGTMspAfik/9Gu9qoevAKXy +BRqgN5m5HMfoGPeEjzILzaGq8bnPKIOfJ0iAYVkjjIa73Vn20uTmNgNZIRqHqwfw +5GUFHn6cjQXFcQ3ngywgwQD7/h/65w8dBbGysF551sAqzPJRbneQL9Wtklcqi1ub +55NyF0ifT67RqMh+EyxhuhXP1Hi57PTEAeqaFMFxnPlQPb+8pQ8nszWBmI+vUN8D +FmhwCtSTnmKlj0jeAqevmkijJhGPQQ== +=fk/F +-----END PGP SIGNATURE----- diff --git a/SOURCES/shadow-bsd.txt b/SOURCES/shadow-bsd.txt new file mode 100644 index 0000000..a2c1609 --- /dev/null +++ b/SOURCES/shadow-bsd.txt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1990 - 1994, Julianne Frances Haugh + * Copyright (c) 1996 - 2000, Marek Michałkiewicz + * Copyright (c) 2000 - 2006, Tomasz Kłoczko + * Copyright (c) 2007 - 2011, Nicolas François + * All rights reserved. + * + * 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, this list of conditions and the following disclaimer. + * 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 copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``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 COPYRIGHT + * HOLDERS OR CONTRIBUTORS 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. + */ + diff --git a/SOURCES/shadow-utils.login.defs b/SOURCES/shadow-utils.login.defs index 3f27f88..0adfb66 100644 --- a/SOURCES/shadow-utils.login.defs +++ b/SOURCES/shadow-utils.login.defs @@ -68,5 +68,5 @@ UMASK 077 USERGROUPS_ENAB yes # Use SHA512 to encrypt password. -ENCRYPT_METHOD SHA512 +ENCRYPT_METHOD SHA512 diff --git a/SPECS/shadow-utils.spec b/SPECS/shadow-utils.spec index f67f3f7..cba6d81 100644 --- a/SPECS/shadow-utils.spec +++ b/SPECS/shadow-utils.spec @@ -1,50 +1,52 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.1.5.1 -Release: 25%{?dist}.1 +Version: 4.6 +Release: 5%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ -Source0: http://pkg-shadow.alioth.debian.org/releases/shadow-%{version}.tar.bz2 -Source3: http://pkg-shadow.alioth.debian.org/releases/shadow-%{version}.tar.bz2.sig -Source1: shadow-utils.login.defs +Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz.asc Source2: shadow-utils.useradd -Patch0: shadow-4.1.5-redhat.patch -Patch1: shadow-4.1.5.1-goodname.patch +Source3: shadow-utils.login.defs +Source4: shadow-bsd.txt +Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +Patch0: shadow-4.6-redhat.patch +Patch1: shadow-4.5-goodname.patch Patch2: shadow-4.1.5.1-info-parent-dir.patch -Patch3: shadow-4.1.5-uflg.patch -Patch6: shadow-4.1.5.1-selinux.patch -Patch7: shadow-4.1.5-2ndskip.patch -Patch8: shadow-4.1.5.1-backup-mode.patch -Patch9: shadow-4.1.5.1-merge-group.patch -Patch10: shadow-4.1.5.1-orig-context.patch +Patch6: shadow-4.6-selinux.patch +Patch10: shadow-4.6-orig-context.patch Patch11: shadow-4.1.5.1-logmsg.patch -Patch12: shadow-4.1.5.1-errmsg.patch -Patch13: shadow-4.1.5.1-audit-owner.patch Patch14: shadow-4.1.5.1-default-range.patch -Patch15: shadow-4.1.5.1-manfix.patch -Patch16: shadow-4.1.5.1-crypt-null.patch +Patch15: shadow-4.3.1-manfix.patch Patch17: shadow-4.1.5.1-userdel-helpfix.patch -Patch18: shadow-4.1.5.1-date-parsing.patch -Patch19: shadow-4.1.5.1-ingroup.patch -Patch20: shadow-4.1.5.1-move-home.patch -Patch21: shadow-4.1.5.1-audit-update.patch -Patch22: shadow-4.1.5.1-ja-translation.patch -Patch23: shadow-4.1.5.1-usermod-passwd.patch -Patch24: shadow-4.1.5.1-id-alloc.patch -Patch25: shadow-4.1.5.1-lastlog-unexpire.patch -Patch26: shadow-4.1.5.1-chgrp-guard.patch -Patch27: shadow-4.1.5.1-selinux-perms.patch -Patch28: shadow-4.1.5.1-null-tm.patch -Patch29: shadow-4.1.5.1-long-entry.patch +Patch19: shadow-4.2.1-date-parsing.patch +Patch21: shadow-4.6-move-home.patch +Patch22: shadow-4.6-audit-update.patch +Patch23: shadow-4.5-usermod-unlock.patch +Patch24: shadow-4.2.1-no-lock-dos.patch +Patch28: shadow-4.3.1-selinux-perms.patch +Patch29: shadow-4.2.1-null-tm.patch +Patch31: shadow-4.6-getenforce.patch +Patch32: shadow-4.5-crypt_h.patch +Patch33: shadow-4.5-long-entry.patch +Patch34: shadow-4.6-usermod-crash.patch +Patch35: shadow-4.6-coverity.patch +Patch36: shadow-4.6-use-itstool.patch +Patch38: shadow-4.6-sysugid-min-limit.patch +Patch39: shadow-4.6-chgrp-guard.patch +Patch40: shadow-4.6-ignore-login-prompt.patch +Patch41: shadow-4.6-use-lckpwdf.patch License: BSD and GPLv2+ Group: System Environment/Base +BuildRequires: gcc BuildRequires: libselinux-devel >= 1.25.2-1 BuildRequires: audit-libs-devel >= 1.6.5 BuildRequires: libsemanage-devel -BuildRequires: libacl-devel libattr-devel -BuildRequires: gnome-doc-utils docbook-style-xsl gettext -#BuildRequires: autoconf, automake, libtool, gettext-devel +BuildRequires: libacl-devel, libattr-devel +BuildRequires: bison, flex, docbook-style-xsl, docbook-dtds +BuildRequires: autoconf, automake, libtool, gettext-devel +BuildRequires: /usr/bin/xsltproc, /usr/bin/itstool Requires: libselinux >= 1.25.2-1 Requires: audit-libs >= 1.6.5 Requires: setup @@ -69,44 +71,39 @@ are used for managing group accounts. %patch0 -p1 -b .redhat %patch1 -p1 -b .goodname %patch2 -p1 -b .info-parent-dir -%patch3 -p1 -b .uflg %patch6 -p1 -b .selinux -%patch7 -p1 -b .2ndskip -%patch8 -p1 -b .backup-mode -%patch9 -p1 -b .merge-group %patch10 -p1 -b .orig-context %patch11 -p1 -b .logmsg -%patch12 -p1 -b .errmsg -%patch13 -p1 -b .audit-owner %patch14 -p1 -b .default-range %patch15 -p1 -b .manfix -%patch16 -p1 -b .crypt-null %patch17 -p1 -b .userdel -%patch18 -p1 -b .date-parsing -%patch19 -p1 -b .ingroup -%patch20 -p1 -b .move-home -%patch21 -p1 -b .audit-update -%patch22 -p1 -b .ja-translation -%patch23 -p1 -b .usermod-passwd -%patch24 -p1 -b .id-alloc -%patch25 -p1 -b .unexpire -%patch26 -p1 -b .chgrp-guard -%patch27 -p1 -b .selinux-perms -%patch28 -p1 -b .null-tm -%patch29 -p1 -b .long-entry +%patch19 -p1 -b .date-parsing +%patch21 -p1 -b .move-home +%patch22 -p1 -b .audit-update +%patch23 -p1 -b .unlock +%patch24 -p1 -b .no-lock-dos +%patch28 -p1 -b .selinux-perms +%patch29 -p1 -b .null-tm +%patch31 -p1 -b .getenforce +%patch32 -p1 -b .crypt_h +%patch33 -p1 -b .long-entry +%patch34 -p1 -b .usermod-crash +%patch35 -p1 -b .coverity +%patch36 -p1 -b .use-itstool +%patch38 -p1 -b .sysugid-min-limit +%patch39 -p1 -b .chgrp-guard +%patch40 -p1 -b .login-prompt +%patch41 -p1 -b .use-lckpwdf iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO -#rm po/*.gmo -#rm po/stamp-po -#aclocal -#libtoolize --force -#automake -a -#autoconf +cp -a %{SOURCE4} %{SOURCE5} . -%build +# Force regeneration of getdate.c +rm libmisc/getdate.c +%build %ifarch sparc64 #sparc64 need big PIE export CFLAGS="$RPM_OPT_FLAGS -fPIE" @@ -115,8 +112,9 @@ export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" export CFLAGS="$RPM_OPT_FLAGS -fpie" export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" %endif - -export LC_ALL=C +aclocal +libtoolize -f +autoreconf -f %configure \ --enable-shadowgrp \ --enable-man \ @@ -127,20 +125,17 @@ export LC_ALL=C --without-libpam \ --disable-shared \ --with-group-name-max-length=32 -# update the japanese translation -(cd po; make ja.gmo) -make +%make_build %install rm -rf $RPM_BUILD_ROOT -make install DESTDIR=$RPM_BUILD_ROOT gnulocaledir=$RPM_BUILD_ROOT/%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs +%make_install gnulocaledir=$RPM_BUILD_ROOT/%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs install -d -m 755 $RPM_BUILD_ROOT/%{_sysconfdir}/default -install -p -c -m 0644 %{SOURCE1} $RPM_BUILD_ROOT/%{_sysconfdir}/login.defs +install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/%{_sysconfdir}/login.defs install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/default/useradd ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser -#ln -s %{_mandir}/man8/useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8 ln -s useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8 for subdir in $RPM_BUILD_ROOT/%{_mandir}/{??,??_??,??_??.*}/man* ; do test -d $subdir && test -e $subdir/useradd.8 && echo ".so man8/useradd.8" > $subdir/adduser.8 @@ -159,7 +154,6 @@ rm $RPM_BUILD_ROOT/%{_sysconfdir}/login.access rm $RPM_BUILD_ROOT/%{_sysconfdir}/limits rm $RPM_BUILD_ROOT/%{_sbindir}/logoutd rm $RPM_BUILD_ROOT/%{_sbindir}/nologin -rm $RPM_BUILD_ROOT/%{_sbindir}/chgpasswd rm $RPM_BUILD_ROOT/%{_mandir}/man1/chfn.* rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/chfn.* rm $RPM_BUILD_ROOT/%{_mandir}/man1/chsh.* @@ -188,8 +182,6 @@ rm $RPM_BUILD_ROOT/%{_mandir}/man8/logoutd.* rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/logoutd.* rm $RPM_BUILD_ROOT/%{_mandir}/man8/nologin.* rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/nologin.* -rm $RPM_BUILD_ROOT/%{_mandir}/man8/chgpasswd.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/chgpasswd.* rm $RPM_BUILD_ROOT/%{_mandir}/man3/getspnam.* rm $RPM_BUILD_ROOT/%{_mandir}/*/man3/getspnam.* rm $RPM_BUILD_ROOT/%{_mandir}/man5/faillog.* @@ -207,12 +199,10 @@ for dir in $(ls -1d $RPM_BUILD_ROOT%{_mandir}/{??,??_??}) ; do echo "%%lang($lang) $dir/man*/*" >> shadow.lang done -%clean -rm -rf $RPM_BUILD_ROOT - %files -f shadow.lang -%defattr(-,root,root) %doc NEWS doc/HOWTO README +%{!?_licensedir:%global license %%doc} +%license gpl-2.0.txt shadow-bsd.txt %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/login.defs %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/default/useradd %{_bindir}/sg @@ -220,13 +210,16 @@ rm -rf $RPM_BUILD_ROOT %attr(4755,root,root) %{_bindir}/gpasswd %{_bindir}/lastlog %attr(4755,root,root) %{_bindir}/newgrp +%attr(0755,root,root) %caps(cap_setgid=ep) %{_bindir}/newgidmap +%attr(0755,root,root) %caps(cap_setuid=ep) %{_bindir}/newuidmap %{_sbindir}/adduser -%attr(0750,root,root) %{_sbindir}/user* -%attr(0750,root,root) %{_sbindir}/group* +%attr(0755,root,root) %{_sbindir}/user* +%attr(0755,root,root) %{_sbindir}/group* %{_sbindir}/grpck %{_sbindir}/pwck %{_sbindir}/*conv %{_sbindir}/chpasswd +%{_sbindir}/chgpasswd %{_sbindir}/newusers %{_sbindir}/vipw %{_sbindir}/vigr @@ -234,16 +227,21 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man1/gpasswd.1* %{_mandir}/man1/sg.1* %{_mandir}/man1/newgrp.1* +%{_mandir}/man1/newgidmap.1* +%{_mandir}/man1/newuidmap.1* %{_mandir}/man3/shadow.3* %{_mandir}/man5/shadow.5* %{_mandir}/man5/login.defs.5* %{_mandir}/man5/gshadow.5* +%{_mandir}/man5/subuid.5* +%{_mandir}/man5/subgid.5* %{_mandir}/man8/adduser.8* %{_mandir}/man8/group*.8* %{_mandir}/man8/user*.8* %{_mandir}/man8/pwck.8* %{_mandir}/man8/grpck.8* %{_mandir}/man8/chpasswd.8* +%{_mandir}/man8/chgpasswd.8* %{_mandir}/man8/newusers.8* %{_mandir}/man8/*conv.8* %{_mandir}/man8/lastlog.8* @@ -251,9 +249,26 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man8/vigr.8* %changelog -* Fri Feb 1 2019 Tomáš Mráz - 2:4.1.5.1-25.1 +* Fri May 3 2019 Tomáš Mráz - 2:4.6-5 +- use lckpwdf() again to disable concurrent edits of databases by + other applications + +* Wed Apr 3 2019 Tomáš Mráz - 2:4.6-4 +- force regeneration of getdate.c otherwise the date parsing fix + is not applied + +* Fri Mar 22 2019 Tomáš Mráz - 2:4.6-3 +- clarify chage manual page in regards to shadow and passwd + inconsistency (#1686440) + +* Thu Mar 21 2019 Tomáš Mráz - 2:4.6-2 +- ignore LOGIN_PLAIN_PROMPT variable in login.defs +- correct wrong SUB_UID/GID_COUNT default in manual page (#1690522) + +* Tue Jan 22 2019 Tomáš Mráz - 2:4.6-1 +- rebase to current upstream release to bring newuidmap and newgidmap - re-allow all numeric usernames when SHADOW_ALLOW_ALL_NUMERIC_USER - environment variable is set (#1651450) + environment variable is set * Tue Apr 24 2018 Tomáš Mráz - 2:4.1.5.1-25 - prevent creating users ".." or "." or with all numeric usernames (#1373645)