diff --git a/.fmf/version b/.fmf/version
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/.fmf/version
@@ -0,0 +1 @@
+1
diff --git a/.gitignore b/.gitignore
index e78a553..3023995 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,52 @@ shadow-4.1.4.2.tar.bz2
/shadow-4.1.5.1.tar.bz2.sig
/shadow-4.2.1.tar.xz
/shadow-4.2.1.tar.xz.sig
+/shadow-4.3.1.tar.gz
+/shadow-4.5.tar.xz
+/shadow-4.5.tar.xz.asc
+/shadow-4.6.tar.xz
+/shadow-4.6.tar.xz.asc
+/shadow-4.8.tar.xz
+/shadow-4.8.tar.xz.asc
+/shadow-4.8.1.tar.xz
+/shadow-4.8.1.tar.xz.asc
+/shadow-4.9.tar.xz
+/shadow-4.9.tar.xz.asc
+/shadow-4.11.1.tar.xz
+/shadow-4.11.1.tar.xz.asc
+/shadow-4.12.3.tar.xz
+/shadow-4.12.3.tar.xz.asc
+/shadow-4.13.tar.xz
+/shadow-4.13.tar.xz.asc
+/shadow-4.14.0.tar.xz
+/shadow-4.14.0.tar.xz.asc
+/shadow-4.15.0rc2.tar.xz
+/shadow-4.15.0rc2.tar.xz.asc
+/shadow-4.15.0rc3.tar.xz
+/shadow-4.15.0rc3.tar.xz.asc
+/shadow-4.15.0.tar.xz
+/shadow-4.15.0.tar.xz.asc
+/shadow-4.15.1.tar.xz
+/shadow-4.15.1.tar.xz.asc
+/shadow-4.16.0.tar.xz
+/shadow-4.16.0.tar.xz.asc
+/shadow-4.17.0-rc1.tar.xz
+/shadow-4.17.0-rc1.tar.xz.asc
+/shadow-4.17.0.tar.xz
+/shadow-4.17.0.tar.xz.asc
+/shadow-4.17.4.tar.xz
+/shadow-4.17.4.tar.xz.asc
+/shadow-4.18.0.tar.xz
+/shadow-4.18.0.tar.xz.asc
+/shadow-4.19.0.tar.xz
+/shadow-4.19.0.tar.xz.asc
+/shadow-4.19.2.tar.xz
+/shadow-4.19.2.tar.xz.asc
+/shadow-4.19.3.tar.xz
+/shadow-4.19.3.tar.xz.asc
+/shadow-4.20.0-rc2.tar.xz
+/shadow-4.20.0-rc2.tar.xz.asc
+/shadow-4.20.0-rc3.tar.xz
+/shadow-4.20.0-rc3.tar.xz.asc
+/shadow-4.20.0.tar.xz
+/shadow-4.20.0.tar.xz.asc
diff --git a/passwd.pamd b/passwd.pamd
new file mode 100644
index 0000000..fd03d03
--- /dev/null
+++ b/passwd.pamd
@@ -0,0 +1,5 @@
+#%PAM-1.0
+# This tool only uses the password stack.
+password substack system-auth
+-password optional pam_gnome_keyring.so use_authtok
+password substack postlogin
diff --git a/plans/tier0-functional.fmf b/plans/tier0-functional.fmf
new file mode 100644
index 0000000..a9939b5
--- /dev/null
+++ b/plans/tier0-functional.fmf
@@ -0,0 +1,51 @@
+summary: Tier 0 functional tests for shadow-utils
+description: |
+ Run comprehensive system tests for shadow-utils. These tests validate user and group
+ account management functionality by testing actual system operations including user
+ creation, password management, group operations, and verification of system files
+ (i.e. /etc/passwd, /etc/shadow).
+
+provision:
+ how: virtual
+ image: fedora
+
+prepare:
+ - name: Install general dependencies
+ how: install
+ package:
+ - expect
+ - gcc
+ - git
+ - libssh-devel
+ - python3-devel
+ - python3-pip
+
+ - name: Setup SSH keys for localhost testing
+ how: shell
+ script:
+ - ssh-keygen -t rsa -f /root/.ssh/id_rsa -N "" -q
+ - cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
+ - chmod 600 /root/.ssh/authorized_keys
+ - ssh-keyscan -H localhost >> /root/.ssh/known_hosts
+
+ - name: Clone shadow repository
+ how: shell
+ script:
+ - git clone https://github.com/shadow-maint/shadow.git /tmp/shadow-test
+
+ - name: Copy test topology for Fedora CI
+ how: shell
+ script:
+ - cp tests/mhc-fedora-ci.yaml /tmp/shadow-test/tests/system
+
+ - name: Install test dependencies
+ how: shell
+ script:
+ - pip3 install -r /tmp/shadow-test/tests/system/requirements.txt
+
+execute:
+ how: tmt
+ duration: 30m
+ script: |
+ cd /tmp/shadow-test/tests/system
+ pytest --mh-config=mhc-fedora-ci.yaml --mh-lazy-ssh -v
diff --git a/shadow-4.1.5-2ndskip.patch b/shadow-4.1.5-2ndskip.patch
deleted file mode 100644
index 8a9cf68..0000000
--- a/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/shadow-4.1.5-redhat.patch b/shadow-4.1.5-redhat.patch
deleted file mode 100644
index a785b29..0000000
--- a/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/shadow-4.1.5-uflg.patch b/shadow-4.1.5-uflg.patch
deleted file mode 100644
index f72bca3..0000000
--- a/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/shadow-4.1.5.1-audit-owner.patch b/shadow-4.1.5.1-audit-owner.patch
deleted file mode 100644
index 6fbbdbf..0000000
--- a/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/shadow-4.1.5.1-backup-mode.patch b/shadow-4.1.5.1-backup-mode.patch
deleted file mode 100644
index 7366b86..0000000
--- a/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/shadow-4.1.5.1-default-range.patch b/shadow-4.1.5.1-default-range.patch
deleted file mode 100644
index 45c677a..0000000
--- a/shadow-4.1.5.1-default-range.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-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
-@@ -143,6 +143,7 @@ static int semanage_user_mod (semanage_h
- goto done;
- }
-
-+#if 0
- ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
- if (ret != 0) {
- fprintf (stderr,
-@@ -150,6 +151,7 @@ static int semanage_user_mod (semanage_h
- ret = 1;
- goto done;
- }
-+#endif
-
- ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
- if (ret != 0) {
-@@ -200,6 +202,7 @@ static int semanage_user_add (semanage_h
- goto done;
- }
-
-+#if 0
- ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
- if (ret != 0) {
- fprintf (stderr,
-@@ -208,6 +211,7 @@ static int semanage_user_add (semanage_h
- ret = 1;
- goto done;
- }
-+#endif
-
- ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
- if (ret != 0) {
diff --git a/shadow-4.1.5.1-errmsg.patch b/shadow-4.1.5.1-errmsg.patch
deleted file mode 100644
index 6f3a1d2..0000000
--- a/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/shadow-4.1.5.1-goodname.patch b/shadow-4.1.5.1-goodname.patch
deleted file mode 100644
index 15c98a7..0000000
--- a/shadow-4.1.5.1-goodname.patch
+++ /dev/null
@@ -1,99 +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 2014-09-09 17:35:17.207303124 +0200
-@@ -47,27 +47,42 @@
- #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.
-+ */
-+ int numeric;
-+
-+ if ( ('\0' == *name) ||
-+ !((*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;
- }
-
- 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 2014-09-09 17:28:46.330300342 +0200
-@@ -259,12 +259,6 @@
-
- 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 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 2014-09-09 17:28:46.330300342 +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,12 +654,6 @@
-
-
-
-- 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 only be up to 32 characters long.
-
-
diff --git a/shadow-4.1.5.1-id-alloc.patch b/shadow-4.1.5.1-id-alloc.patch
deleted file mode 100644
index df6f89f..0000000
--- a/shadow-4.1.5.1-id-alloc.patch
+++ /dev/null
@@ -1,1219 +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 three 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).
-
-3) This patch also adds better error-handling for errno from
-getgrgid(), since if this function returns an unexpected error, we
-should not be treating it as "ID is available". This could result
-in assigning a GID that was already in use, with all the same
-issues as 1) above.
-
-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/shadow-4.1.5.1-info-parent-dir.patch b/shadow-4.1.5.1-info-parent-dir.patch
deleted file mode 100644
index b05e5bb..0000000
--- a/shadow-4.1.5.1-info-parent-dir.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-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 @@
-
- If this field does not specify an existing directory, the
- specified directory is created, with ownership set to the
-- user being created or updated and its primary group.
-+ user being created or updated and its primary group. Note
-+ that newusers does not create parent directories of the new
-+ user's home directory. The newusers command will fail to
-+ create the home directory if the parent directories do not
-+ exist, and will send a message to stderr informing the user
-+ of the failure. The newusers command will not halt or return
-+ a failure to the calling shell if it fails to create the home
-+ directory, it will continue to process the batch of new users
-+ specified.
-
-
- If the home directory of an existing user is changed,
diff --git a/shadow-4.1.5.1-ingroup.patch b/shadow-4.1.5.1-ingroup.patch
deleted file mode 100644
index e440431..0000000
--- a/shadow-4.1.5.1-ingroup.patch
+++ /dev/null
@@ -1,63 +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 2014-08-29 13:31:38.000000000 +0200
-+++ shadow-4.1.5.1/src/newgrp.c 2014-08-29 14:04:57.183849650 +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;
-@@ -616,7 +624,7 @@ int main (int argc, char **argv)
- * groups of the same GID like the requested group for
- * membership of the current user.
- */
-- grp = find_matching_group (name, grp->gr_gid);
-+ grp = find_matching_group (name, grp);
- if (NULL == grp) {
- /*
- * No matching group found. As we already know that
diff --git a/shadow-4.1.5.1-logmsg.patch b/shadow-4.1.5.1-logmsg.patch
deleted file mode 100644
index 7d5cbc8..0000000
--- a/shadow-4.1.5.1-logmsg.patch
+++ /dev/null
@@ -1,12 +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-03-19 18:40:04.908292810 +0100
-@@ -275,7 +275,7 @@ static void fail_exit (int code)
- user_name, AUDIT_NO_ID,
- SHADOW_AUDIT_FAILURE);
- #endif
-- SYSLOG ((LOG_INFO, "failed adding user '%s', data deleted", user_name));
-+ SYSLOG ((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code));
- exit (code);
- }
-
diff --git a/shadow-4.1.5.1-move-home.patch b/shadow-4.1.5.1-move-home.patch
deleted file mode 100644
index c87e232..0000000
--- a/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/shadow-4.1.5.1-orig-context.patch b/shadow-4.1.5.1-orig-context.patch
deleted file mode 100644
index c1ddb13..0000000
--- a/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/shadow-4.1.5.1-selinux.patch b/shadow-4.1.5.1-selinux.patch
deleted file mode 100644
index 4ac32d2..0000000
--- a/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/shadow-4.1.5.1-userdel-helpfix.patch b/shadow-4.1.5.1-userdel-helpfix.patch
deleted file mode 100644
index b79baee..0000000
--- a/shadow-4.1.5.1-userdel-helpfix.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-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)
- "\n"
- "Options:\n"),
- Prog);
-- (void) fputs (_(" -f, --force force removal of files,\n"
-- " even if not owned by user\n"),
-+ (void) fputs (_(" -f, --force force some actions that would fail otherwise\n"
-+ " e.g. removal of user still logged in\n"
-+ " or files, even if not owned by the user\n"),
- usageout);
- (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
- (void) fputs (_(" -r, --remove remove home directory and mail spool\n"), usageout);
diff --git a/shadow-4.2.1-audit-update.patch b/shadow-4.2.1-audit-update.patch
deleted file mode 100644
index 8f2edf8..0000000
--- a/shadow-4.2.1-audit-update.patch
+++ /dev/null
@@ -1,2347 +0,0 @@
-diff -up shadow-4.2.1/libmisc/audit_help.c.audit-update shadow-4.2.1/libmisc/audit_help.c
---- shadow-4.2.1/libmisc/audit_help.c.audit-update 2014-03-01 18:50:05.000000000 +0100
-+++ shadow-4.2.1/libmisc/audit_help.c 2014-11-26 15:06:24.663660558 +0100
-@@ -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.2.1/libmisc/cleanup_group.c.audit-update shadow-4.2.1/libmisc/cleanup_group.c
---- shadow-4.2.1/libmisc/cleanup_group.c.audit-update 2014-03-01 18:50:05.000000000 +0100
-+++ shadow-4.2.1/libmisc/cleanup_group.c 2014-11-26 15:06:24.663660558 +0100
-@@ -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.2.1/libmisc/cleanup_user.c.audit-update shadow-4.2.1/libmisc/cleanup_user.c
---- shadow-4.2.1/libmisc/cleanup_user.c.audit-update 2014-03-01 18:50:05.000000000 +0100
-+++ shadow-4.2.1/libmisc/cleanup_user.c 2014-11-26 15:06:24.663660558 +0100
-@@ -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.2.1/lib/prototypes.h.audit-update shadow-4.2.1/lib/prototypes.h
---- shadow-4.2.1/lib/prototypes.h.audit-update 2014-11-26 15:06:24.644660498 +0100
-+++ shadow-4.2.1/lib/prototypes.h 2014-11-26 15:06:24.663660558 +0100
-@@ -208,12 +208,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.2.1/src/gpasswd.c.audit-update shadow-4.2.1/src/gpasswd.c
---- shadow-4.2.1/src/gpasswd.c.audit-update 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/src/gpasswd.c 2014-11-26 15:06:24.664660561 +0100
-@@ -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 -up shadow-4.2.1/src/groupadd.c.audit-update shadow-4.2.1/src/groupadd.c
---- shadow-4.2.1/src/groupadd.c.audit-update 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/src/groupadd.c 2014-11-26 15:06:24.664660561 +0100
-@@ -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 -up shadow-4.2.1/src/groupdel.c.audit-update shadow-4.2.1/src/groupdel.c
---- shadow-4.2.1/src/groupdel.c.audit-update 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/src/groupdel.c 2014-11-26 15:06:24.665660564 +0100
-@@ -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 -up shadow-4.2.1/src/groupmod.c.audit-update shadow-4.2.1/src/groupmod.c
---- shadow-4.2.1/src/groupmod.c.audit-update 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/src/groupmod.c 2014-11-26 15:06:24.665660564 +0100
-@@ -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 -up shadow-4.2.1/src/chage.c.audit-update shadow-4.2.1/src/chage.c
---- shadow-4.2.1/src/chage.c.audit-update 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/src/chage.c 2014-11-26 15:06:24.663660558 +0100
-@@ -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.2.1/src/newgrp.c.audit-update shadow-4.2.1/src/newgrp.c
---- shadow-4.2.1/src/newgrp.c.audit-update 2014-11-26 15:06:24.660660548 +0100
-+++ shadow-4.2.1/src/newgrp.c 2014-11-26 15:06:24.666660567 +0100
-@@ -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);
- }
-
-@@ -317,15 +306,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);
-@@ -451,7 +452,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 ()));
-@@ -567,15 +568,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);
-@@ -716,10 +728,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);
- }
-@@ -728,10 +740,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);
- }
-@@ -745,10 +757,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);
-@@ -812,11 +824,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
-@@ -840,15 +852,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.2.1/src/useradd.c.audit-update shadow-4.2.1/src/useradd.c
---- shadow-4.2.1/src/useradd.c.audit-update 2014-11-26 15:06:24.648660511 +0100
-+++ shadow-4.2.1/src/useradd.c 2014-11-26 15:14:02.446087183 +0100
-@@ -222,6 +222,8 @@ static void create_mail (void);
- */
- static void fail_exit (int code)
- {
-+ int type;
-+
- if (home_added) {
- if (rmdir (user_home) != 0) {
- fprintf (stderr,
-@@ -235,12 +237,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 */
- }
- }
-@@ -248,12 +244,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 */
- }
- }
-@@ -261,12 +251,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 */
- }
- }
-@@ -275,12 +259,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 */
- }
- }
-@@ -290,12 +268,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 */
- }
- }
-@@ -303,20 +275,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
-@@ -623,7 +594,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
-@@ -893,12 +864,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 */
- }
-
-@@ -912,18 +877,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,
-@@ -968,12 +927,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 */
- }
-
-@@ -987,18 +940,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,
-@@ -1341,7 +1289,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
-@@ -1444,7 +1392,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
-@@ -1457,7 +1405,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
-@@ -1469,7 +1417,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
-@@ -1483,7 +1431,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
-@@ -1499,7 +1447,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
-@@ -1513,7 +1461,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
-@@ -1705,7 +1653,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
-@@ -1721,7 +1669,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
-@@ -1731,7 +1679,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
-@@ -1846,12 +1794,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
-@@ -1873,7 +1815,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
-@@ -1908,12 +1850,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);
-@@ -1921,8 +1857,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
-@@ -2098,12 +2034,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);
- }
-
-@@ -2119,12 +2049,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);
- }
- }
-@@ -2154,12 +2078,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);
- }
- }
-@@ -2223,9 +2141,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.2.1/src/userdel.c.audit-update shadow-4.2.1/src/userdel.c
---- shadow-4.2.1/src/userdel.c.audit-update 2014-11-26 15:06:24.655660533 +0100
-+++ shadow-4.2.1/src/userdel.c 2014-11-26 15:16:01.892459425 +0100
-@@ -214,9 +214,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",
-@@ -276,9 +276,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",
-@@ -355,9 +355,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,
-@@ -373,9 +373,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,
-@@ -537,7 +537,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 */
-@@ -557,24 +557,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) {
-@@ -582,12 +570,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;
-@@ -595,12 +577,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);
- }
- }
-@@ -608,23 +584,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
-@@ -633,24 +597,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);
- }
- }
-@@ -661,24 +613,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_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);
- }
- }
-@@ -687,24 +627,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_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);
- }
- }
-@@ -749,7 +677,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 */
-@@ -843,7 +771,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 */
-@@ -859,7 +787,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 */
-@@ -869,8 +797,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);
- }
-@@ -887,7 +815,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 */
-@@ -902,7 +830,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 */
-@@ -912,8 +840,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);
- }
-@@ -1111,7 +1039,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 */
-@@ -1155,7 +1083,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 */
-@@ -1232,8 +1160,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);
- }
-@@ -1242,7 +1170,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);
- }
-@@ -1255,8 +1183,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.2.1/src/usermod.c.audit-update shadow-4.2.1/src/usermod.c
---- shadow-4.2.1/src/usermod.c.audit-update 2014-11-26 15:06:24.661660551 +0100
-+++ shadow-4.2.1/src/usermod.c 2014-11-26 15:17:38.580760741 +0100
-@@ -447,8 +447,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, "!");
-@@ -467,8 +467,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;
-@@ -479,7 +479,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));
-@@ -508,8 +508,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,
-@@ -529,8 +529,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,
-@@ -540,8 +540,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,
-@@ -551,8 +551,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;
-@@ -560,8 +560,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,
-@@ -571,8 +571,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,
-@@ -602,8 +602,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,
-@@ -619,8 +619,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,
-@@ -703,9 +703,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);
- }
-@@ -759,9 +759,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'",
-@@ -775,9 +778,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'",
-@@ -790,9 +795,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));
-@@ -867,9 +874,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'",
-@@ -889,9 +897,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'",
-@@ -905,9 +914,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'",
-@@ -920,9 +930,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));
-@@ -1810,8 +1821,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
-@@ -1829,8 +1840,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
-@@ -1849,9 +1860,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);
-@@ -2055,8 +2066,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
-@@ -2074,8 +2085,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
-@@ -2217,8 +2228,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 */
-@@ -2230,8 +2241,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 */
-@@ -2269,8 +2280,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/shadow-4.2.1-date-parsing.patch b/shadow-4.2.1-date-parsing.patch
deleted file mode 100644
index 91a85ac..0000000
--- a/shadow-4.2.1-date-parsing.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-diff -up shadow-4.2.1/libmisc/getdate.y.date-parsing shadow-4.2.1/libmisc/getdate.y
---- shadow-4.2.1/libmisc/getdate.y.date-parsing 2014-03-01 18:50:05.000000000 +0100
-+++ shadow-4.2.1/libmisc/getdate.y 2014-11-26 14:58:21.208153924 +0100
-@@ -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/shadow-4.2.1-defs-chroot.patch b/shadow-4.2.1-defs-chroot.patch
deleted file mode 100644
index 827ad40..0000000
--- a/shadow-4.2.1-defs-chroot.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff -up shadow-4.2.1/src/useradd.c.defs-chroot shadow-4.2.1/src/useradd.c
---- shadow-4.2.1/src/useradd.c.defs-chroot 2014-12-01 15:14:58.000000000 +0100
-+++ shadow-4.2.1/src/useradd.c 2015-08-27 15:46:21.935698862 +0200
-@@ -1938,8 +1938,8 @@ int main (int argc, char **argv)
- #endif /* ACCT_TOOLS_SETUID */
-
- /* Needed for userns check */
-- uid_t uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
-- uid_t uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
-+ uid_t uid_min;
-+ uid_t uid_max;
-
- /*
- * Get my name so that I can use it to report errors.
-@@ -1957,6 +1957,9 @@ int main (int argc, char **argv)
- audit_help_open ();
- #endif
-
-+ uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
-+ uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
-+
- sys_ngroups = sysconf (_SC_NGROUPS_MAX);
- user_groups = (char **) xmalloc ((1 + sys_ngroups) * sizeof (char *));
- /*
diff --git a/shadow-4.2.1-lastlog-unexpire.patch b/shadow-4.2.1-lastlog-unexpire.patch
deleted file mode 100644
index 2596820..0000000
--- a/shadow-4.2.1-lastlog-unexpire.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-diff -up shadow-4.2.1/man/lastlog.8.xml.unexpire shadow-4.2.1/man/lastlog.8.xml
---- shadow-4.2.1/man/lastlog.8.xml.unexpire 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/man/lastlog.8.xml 2016-02-03 11:50:20.481293785 +0100
-@@ -105,6 +105,17 @@
-
-
-
-+ ,
-+
-+
-+
-+ Clear lastlog record of an user. This option can be used only together
-+ with ()).
-+
-+
-+
-+
-+
- ,
-
-
-@@ -123,6 +134,17 @@
-
-
-
-+
-+
-+ ,
-+
-+
-+
-+ Set lastlog record of an user to the current time. This option can be
-+ used only together with ()).
-+
-+
-+
-
-
- , DAYS
-diff -up shadow-4.2.1/src/lastlog.c.unexpire shadow-4.2.1/src/lastlog.c
---- shadow-4.2.1/src/lastlog.c.unexpire 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/src/lastlog.c 2016-02-03 11:35:26.971273603 +0100
-@@ -71,6 +71,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 +85,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 +198,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 +286,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 +319,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 +388,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 +416,10 @@ int main (int argc, char **argv)
- exit (EXIT_FAILURE);
- }
-
-- print ();
-+ if (Cflg || Sflg)
-+ update ();
-+ else
-+ print ();
-
- (void) fclose (lastlogfile);
-
-diff -up shadow-4.2.1/src/Makefile.am.unexpire shadow-4.2.1/src/Makefile.am
---- shadow-4.2.1/src/Makefile.am.unexpire 2014-05-08 10:43:11.000000000 +0200
-+++ shadow-4.2.1/src/Makefile.am 2016-02-03 11:35:26.971273603 +0100
-@@ -95,6 +95,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.2.1/src/Makefile.in.unexpire shadow-4.2.1/src/Makefile.in
---- shadow-4.2.1/src/Makefile.in.unexpire 2014-05-09 18:49:48.000000000 +0200
-+++ shadow-4.2.1/src/Makefile.in 2016-02-03 11:35:26.972273609 +0100
-@@ -197,7 +197,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/shadow-4.2.1-manfix.patch b/shadow-4.2.1-manfix.patch
deleted file mode 100644
index 04fcb4a..0000000
--- a/shadow-4.2.1-manfix.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-diff -up shadow-4.2.1/man/groupmems.8.xml.manfix shadow-4.2.1/man/groupmems.8.xml
---- shadow-4.2.1/man/groupmems.8.xml.manfix 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/man/groupmems.8.xml 2015-11-06 14:21:03.013060324 +0100
-@@ -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
--
-
-
-
-diff -up shadow-4.2.1/man/chage.1.xml.manfix shadow-4.2.1/man/chage.1.xml
---- shadow-4.2.1/man/chage.1.xml.manfix 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/man/chage.1.xml 2014-11-26 15:34:51.256978960 +0100
-@@ -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.
-
-
-
-diff -up shadow-4.2.1/man/ja/man5/login.defs.5.manfix shadow-4.2.1/man/ja/man5/login.defs.5
---- shadow-4.2.1/man/ja/man5/login.defs.5.manfix 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/man/ja/man5/login.defs.5 2016-01-08 09:58:29.591702354 +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.2.1/man/login.defs.5.xml.manfix shadow-4.2.1/man/login.defs.5.xml
---- shadow-4.2.1/man/login.defs.5.xml.manfix 2014-03-13 06:52:55.000000000 +0100
-+++ shadow-4.2.1/man/login.defs.5.xml 2016-01-08 09:59:35.854169787 +0100
-@@ -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,26 +263,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
-
-
-@@ -282,14 +273,6 @@
-
-
-
--
-- chsh
--
--
-- CHSH_AUTH LOGIN_STRING
--
--
--
-
-
-
-@@ -350,34 +333,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 +360,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 +386,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.2.1/man/shadow.5.xml.manfix shadow-4.2.1/man/shadow.5.xml
---- shadow-4.2.1/man/shadow.5.xml.manfix 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/man/shadow.5.xml 2015-10-27 16:54:29.304231353 +0100
-@@ -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
-diff -up shadow-4.2.1/man/useradd.8.xml.manfix shadow-4.2.1/man/useradd.8.xml
---- shadow-4.2.1/man/useradd.8.xml.manfix 2014-11-26 15:34:51.234978891 +0100
-+++ shadow-4.2.1/man/useradd.8.xml 2014-11-26 15:34:51.257978963 +0100
-@@ -347,11 +347,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.2.1/man/usermod.8.xml.manfix shadow-4.2.1/man/usermod.8.xml
---- shadow-4.2.1/man/usermod.8.xml.manfix 2014-03-01 19:59:51.000000000 +0100
-+++ shadow-4.2.1/man/usermod.8.xml 2014-11-26 15:34:51.257978963 +0100
-@@ -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/shadow-4.2.1-merge-group.patch b/shadow-4.2.1-merge-group.patch
deleted file mode 100644
index 1adcabd..0000000
--- a/shadow-4.2.1-merge-group.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff -up shadow-4.2.1/lib/groupio.c.merge-group shadow-4.2.1/lib/groupio.c
---- shadow-4.2.1/lib/groupio.c.merge-group 2014-11-26 14:33:54.039581662 +0100
-+++ shadow-4.2.1/lib/groupio.c 2014-11-26 14:46:02.841852886 +0100
-@@ -335,8 +335,7 @@ static /*@null@*/struct commonio_entry *
- errno = ENOMEM;
- return NULL;
- }
-- snprintf(new_line, new_line_len, "%s\n%s", gr1->line, gr2->line);
-- new_line[new_line_len] = '\0';
-+ snprintf(new_line, new_line_len + 1, "%s\n%s", gr1->line, gr2->line);
-
- /* Concatenate the 2 list of members */
- for (i=0; NULL != gptr1->gr_mem[i]; i++);
diff --git a/shadow-4.2.1-no-lock-dos.patch b/shadow-4.2.1-no-lock-dos.patch
deleted file mode 100644
index 58fd605..0000000
--- a/shadow-4.2.1-no-lock-dos.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff -up shadow-4.2.1/lib/commonio.c.no-lock-dos shadow-4.2.1/lib/commonio.c
---- shadow-4.2.1/lib/commonio.c.no-lock-dos 2015-08-27 15:09:17.101537812 +0200
-+++ shadow-4.2.1/lib/commonio.c 2015-08-27 15:11:06.643011248 +0200
-@@ -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/shadow-4.2.1-user-busy.patch b/shadow-4.2.1-user-busy.patch
deleted file mode 100644
index ee7e41a..0000000
--- a/shadow-4.2.1-user-busy.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From d2fa8c5d4b0b19445562daf78d3a62421fe8d6b8 Mon Sep 17 00:00:00 2001
-From: Bastian Blank
-Date: Tue, 17 Nov 2015 10:52:24 -0600
-Subject: [PATCH] Fix user busy errors at userdel
-
-From: Bastian Blank
-Acked-by: Serge Hallyn
----
- libmisc/user_busy.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/libmisc/user_busy.c b/libmisc/user_busy.c
-index db7174a..0db32c3 100644
---- a/libmisc/user_busy.c
-+++ b/libmisc/user_busy.c
-@@ -175,6 +175,9 @@ static int user_busy_processes (const char *name, uid_t uid)
- if (stat ("/", &sbroot) != 0) {
- perror ("stat (\"/\")");
- (void) closedir (proc);
-+#ifdef ENABLE_SUBIDS
-+ sub_uid_close();
-+#endif
- return 0;
- }
-
-@@ -212,6 +215,9 @@ static int user_busy_processes (const char *name, uid_t uid)
-
- if (check_status (name, tmp_d_name, uid) != 0) {
- (void) closedir (proc);
-+#ifdef ENABLE_SUBIDS
-+ sub_uid_close();
-+#endif
- fprintf (stderr,
- _("%s: user %s is currently used by process %d\n"),
- Prog, name, pid);
-@@ -232,6 +238,9 @@ static int user_busy_processes (const char *name, uid_t uid)
- }
- if (check_status (name, task_path+6, uid) != 0) {
- (void) closedir (proc);
-+#ifdef ENABLE_SUBIDS
-+ sub_uid_close();
-+#endif
- fprintf (stderr,
- _("%s: user %s is currently used by process %d\n"),
- Prog, name, pid);
---
-2.5.0
-
diff --git a/shadow-4.2.1-usermod-unlock.patch b/shadow-4.2.1-usermod-unlock.patch
deleted file mode 100644
index 19feecb..0000000
--- a/shadow-4.2.1-usermod-unlock.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-diff -up shadow-4.2.1/src/usermod.c.unlock shadow-4.2.1/src/usermod.c
---- shadow-4.2.1/src/usermod.c.unlock 2016-02-03 11:54:14.977664838 +0100
-+++ shadow-4.2.1/src/usermod.c 2016-02-09 11:52:08.244957222 +0100
-@@ -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) time ((time_t *) 0) / SCALE;
diff --git a/shadow-utils.HOME_MODE.xml b/shadow-utils.HOME_MODE.xml
new file mode 100644
index 0000000..21aa55f
--- /dev/null
+++ b/shadow-utils.HOME_MODE.xml
@@ -0,0 +1,43 @@
+
+
+ (number)
+
+
+ The mode for new home directories. If not specified,
+ the is used to create the mode.
+
+
+ useradd and newusers use this
+ to set the mode of the home directory they create.
+
+
+
diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs
index 3f27f88..e84c7ab 100644
--- a/shadow-utils.login.defs
+++ b/shadow-utils.login.defs
@@ -6,15 +6,121 @@
# /etc/pam.d/system-auth for more information.
#
+#
+# Delay in seconds before being allowed another attempt after a login failure
+# Note: When PAM is used, some modules may enforce a minimum delay (e.g.
+# pam_unix(8) enforces a 2s delay)
+#
+#FAIL_DELAY 3
+
+# Currently FAILLOG_ENAB is not supported
+
+#
+# Enable display of unknown usernames when login(1) failures are recorded.
+#
+#LOG_UNKFAIL_ENAB no
+
+# Currently LOG_OK_LOGINS is not supported
+
+# Currently LASTLOG_ENAB is not supported
+
+#
+# Limit the highest user ID number for which the lastlog entries should
+# be updated.
+#
+# No LASTLOG_UID_MAX means that there is no user ID limit for writing
+# lastlog entries.
+#
+#LASTLOG_UID_MAX
+
+# Currently MAIL_CHECK_ENAB is not supported
+
+# Currently OBSCURE_CHECKS_ENAB is not supported
+
+# Currently PORTTIME_CHECKS_ENAB is not supported
+
+# Currently QUOTAS_ENAB is not supported
+
+# Currently SYSLOG_SU_ENAB is not supported
+
+#
+# Enable "syslog" logging of newgrp(1) and sg(1) activity.
+#
+#SYSLOG_SG_ENAB yes
+
+# Currently CONSOLE is not supported
+
+# Currently SULOG_FILE is not supported
+
+# Currently MOTD_FILE is not supported
+
+# Currently ISSUE_FILE is not supported
+
+# Currently TTYTYPE_FILE is not supported
+
+# Currently FTMP_FILE is not supported
+
+# Currently NOLOGINS_FILE is not supported
+
+# Currently SU_NAME is not supported
+
# *REQUIRED*
# Directory where mailboxes reside, _or_ name of file, relative to the
# home directory. If you _do_ define both, MAIL_DIR takes precedence.
-# QMAIL_DIR is for Qmail
#
-#QMAIL_DIR Maildir
MAIL_DIR /var/spool/mail
#MAIL_FILE .mail
+#
+# If defined, file which inhibits all the usual chatter during the login
+# sequence. If a full pathname, then hushed mode will be enabled if the
+# user's name or shell are found in the file. If not a full pathname, then
+# hushed mode will be enabled if the file exists in the user's home directory.
+#
+#HUSHLOGIN_FILE .hushlogin
+#HUSHLOGIN_FILE /etc/hushlogins
+
+# Currently ENV_TZ is not supported
+
+# Currently ENV_HZ is not supported
+
+#
+# The default PATH settings, for superuser and normal users.
+#
+# (they are minimal, add the rest in the shell startup files)
+#ENV_SUPATH PATH=/sbin:/bin:/usr/sbin:/usr/bin
+#ENV_PATH PATH=/bin:/usr/bin
+
+#
+# Terminal permissions
+#
+# TTYGROUP Login tty will be assigned this group ownership.
+# TTYPERM Login tty will be set to this permission.
+#
+# If you have a write(1) program which is "setgid" to a special group
+# which owns the terminals, define TTYGROUP as the number of such group
+# and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and
+# set TTYPERM to either 622 or 600.
+#
+#TTYGROUP tty
+#TTYPERM 0600
+
+# Currently ERASECHAR, KILLCHAR and ULIMIT are not supported
+
+# Default initial "umask" value used by login(1) on non-PAM enabled systems.
+# Default "umask" value for pam_umask(8) on PAM enabled systems.
+# UMASK is also used by useradd(8) and newusers(8) to set the mode for new
+# home directories if HOME_MODE is not set.
+# 022 is the default value, but 027, or even 077, could be considered
+# for increased privacy. There is no One True Answer here: each sysadmin
+# must make up their mind.
+UMASK 022
+
+# HOME_MODE is used by useradd(8) and newusers(8) to set the mode for new
+# home directories.
+# If HOME_MODE is not set, the value of UMASK is used to create the mode.
+HOME_MODE 0700
+
# Password aging controls:
#
# PASS_MAX_DAYS Maximum number of days a password may be used.
@@ -24,26 +130,142 @@ MAIL_DIR /var/spool/mail
#
PASS_MAX_DAYS 99999
PASS_MIN_DAYS 0
-PASS_MIN_LEN 5
+PASS_MIN_LEN 8
PASS_WARN_AGE 7
+# Currently SU_WHEEL_ONLY is not supported
+
+# Currently CRACKLIB_DICTPATH is not supported
+
#
-# Min/max values for automatic uid selection in useradd
+# Min/max values for automatic uid selection in useradd(8)
#
UID_MIN 1000
UID_MAX 60000
# System accounts
SYS_UID_MIN 201
SYS_UID_MAX 999
+# Extra per user uids
+SUB_UID_MIN 524288
+SUB_UID_MAX 600100000
+SUB_UID_COUNT 65536
#
-# Min/max values for automatic gid selection in groupadd
+# Min/max values for automatic gid selection in groupadd(8)
#
GID_MIN 1000
GID_MAX 60000
# System accounts
SYS_GID_MIN 201
SYS_GID_MAX 999
+# Extra per user group ids
+SUB_GID_MIN 524288
+SUB_GID_MAX 600100000
+SUB_GID_COUNT 65536
+
+#
+# Max number of login(1) retries if password is bad
+#
+#LOGIN_RETRIES 3
+
+#
+# Max time in seconds for login(1)
+#
+#LOGIN_TIMEOUT 60
+
+#
+# Maximum number of attempts to change password if rejected (too easy)
+#
+PASS_CHANGE_TRIES 5
+
+#
+# Warn about weak passwords (but still allow them) if you are root.
+#
+PASS_ALWAYS_WARN yes
+
+#
+# Number of significant characters in the password for crypt().
+# Default is 8, don't change unless your crypt() is better.
+# Ignored if MD5_CRYPT_ENAB set to "yes".
+#
+#PASS_MAX_LEN 8
+
+# Currently CHFN_AUTH is not supported
+
+#
+# Which fields may be changed by regular users using chfn(1) - use
+# any combination of letters "frwh" (full name, room number, work
+# phone, home phone). If not defined, no changes are allowed.
+# For backward compatibility, "yes" = "rwh" and "no" = "frwh".
+#
+#CHFN_RESTRICT rwh
+
+# Currently LOGIN_STRING is not supported
+
+# Currently MD5_CRYPT_ENAB is not supported
+
+#
+# If set to MD5, MD5-based algorithm will be used for encrypting password
+# If set to SHA256, SHA256-based algorithm will be used for encrypting password
+# If set to SHA512, SHA512-based algorithm will be used for encrypting password
+# If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password
+# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password
+# If set to DES, DES-based algorithm will be used for encrypting password (default)
+#
+ENCRYPT_METHOD YESCRYPT
+
+#
+# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
+#
+# Define the number of SHA rounds.
+# With a lot of rounds, it is more difficult to brute-force the password.
+# However, more CPU resources will be needed to authenticate users if
+# this value is increased.
+#
+# If not specified, the libc will choose the default number of rounds (5000).
+# The values must be within the 1000-999999999 range.
+#
+#SHA_CRYPT_MAX_ROUNDS 5000
+
+# Currently SHA_CRYPT_MIN_ROUNDS is not supported
+
+#
+# Only works if ENCRYPT_METHOD is set to BCRYPT.
+#
+# Define the number of BCRYPT rounds.
+# With a lot of rounds, it is more difficult to brute-force the password.
+# However, more CPU resources will be needed to authenticate users if
+# this value is increased.
+#
+# If not specified, 13 rounds will be attempted.
+# If only one of the MIN or MAX values is set, then this value will be used.
+# If MIN > MAX, the highest value will be used.
+#
+#BCRYPT_MIN_ROUNDS 13
+#BCRYPT_MAX_ROUNDS 31
+
+#
+# Only works if ENCRYPT_METHOD is set to YESCRYPT.
+#
+# Define the YESCRYPT cost factor.
+# With a higher cost factor, it is more difficult to brute-force the password.
+# However, more CPU time and more memory will be needed to authenticate users
+# if this value is increased.
+#
+# If not specified, a cost factor of 5 will be used.
+# The value must be within the 1-11 range.
+#
+#YESCRYPT_COST_FACTOR 5
+
+# Currently CONSOLE_GROUPS is not supported
+
+#
+# Should login be allowed if we can't cd to the home directory?
+# Default is yes.
+#
+#DEFAULT_HOME yes
+
+# Currently ENVIRON_FILE is not supported
#
# If defined, this command is run when removing a user.
@@ -53,20 +275,41 @@ SYS_GID_MAX 999
#USERDEL_CMD /usr/sbin/userdel_local
#
-# If useradd should create home directories for users by default
-# On RH systems, we do. This option is overridden with the -m flag on
-# useradd command line.
-#
-CREATE_HOME yes
-
-# The permission mask is initialized to this value. If not specified,
-# the permission mask will be initialized to 022.
-UMASK 077
-
-# This enables userdel to remove user groups if no members exist.
+# Enables userdel(8) to remove user groups if no members exist.
#
USERGROUPS_ENAB yes
-# Use SHA512 to encrypt password.
-ENCRYPT_METHOD SHA512
+#
+# If set to a non-zero number, the shadow utilities will make sure that
+# groups never have more than this number of users on one line.
+# This permits to support split groups (groups split into multiple lines,
+# with the same group ID, to avoid limitation of the line length in the
+# group file).
+#
+# 0 is the default value and disables this feature.
+#
+#MAX_MEMBERS_PER_GROUP 0
+#
+# If useradd(8) should create home directories for users by default (non
+# system users only).
+# This option is overridden with the -M or -m flags on the useradd(8)
+# command-line.
+#
+CREATE_HOME yes
+
+#
+# Force use shadow, even if shadow passwd & shadow group files are
+# missing.
+#
+#FORCE_SHADOW yes
+
+#
+# Select the HMAC cryptography algorithm.
+# Used in pam_timestamp module to calculate the keyed-hash message
+# authentication code.
+#
+# Note: It is recommended to check hmac(3) to see the possible algorithms
+# that are available in your system.
+#
+HMAC_CRYPTO_ALGO SHA512
diff --git a/shadow-utils.spec b/shadow-utils.spec
index b47ae15..7bc7e8b 100644
--- a/shadow-utils.spec
+++ b/shadow-utils.spec
@@ -1,55 +1,74 @@
Summary: Utilities for managing accounts and shadow password files
Name: shadow-utils
-Version: 4.2.1
-Release: 8%{?dist}
+Version: 4.20.0
+Release: 1%{?dist}
Epoch: 2
-URL: http://pkg-shadow.alioth.debian.org/
-Source0: http://pkg-shadow.alioth.debian.org/releases/shadow-%{version}.tar.xz
-Source3: http://pkg-shadow.alioth.debian.org/releases/shadow-%{version}.tar.xz.sig
-Source1: shadow-utils.login.defs
+License: BSD-3-Clause AND GPL-2.0-or-later
+URL: https://github.com/shadow-maint/shadow
+Source0: https://github.com/shadow-maint/shadow/releases/download/4.20.0/shadow-4.20.0.tar.xz
+Source1: https://github.com/shadow-maint/shadow/releases/download/4.20.0/shadow-4.20.0.tar.xz.asc
Source2: shadow-utils.useradd
+Source3: shadow-utils.login.defs
Source4: shadow-bsd.txt
Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
-Patch0: shadow-4.1.5-redhat.patch
-Patch1: shadow-4.1.5.1-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.2.1-merge-group.patch
-Patch10: shadow-4.1.5.1-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.2.1-manfix.patch
-Patch17: shadow-4.1.5.1-userdel-helpfix.patch
-Patch18: shadow-4.1.5.1-id-alloc.patch
-Patch19: shadow-4.2.1-date-parsing.patch
-Patch20: shadow-4.1.5.1-ingroup.patch
-Patch21: shadow-4.1.5.1-move-home.patch
-Patch22: shadow-4.2.1-audit-update.patch
-Patch23: shadow-4.2.1-usermod-unlock.patch
-Patch24: shadow-4.2.1-no-lock-dos.patch
-Patch25: shadow-4.2.1-defs-chroot.patch
-Patch26: shadow-4.2.1-lastlog-unexpire.patch
-Patch27: shadow-4.2.1-user-busy.patch
+Source6: shadow-utils.HOME_MODE.xml
+Source7: passwd.pamd
-License: BSD and GPLv2+
-Group: System Environment/Base
-BuildRequires: libselinux-devel >= 1.25.2-1
-BuildRequires: audit-libs-devel >= 1.6.5
-BuildRequires: libsemanage-devel
-BuildRequires: libacl-devel libattr-devel
-BuildRequires: bison flex gnome-doc-utils
-#BuildRequires: autoconf, automake, libtool, gettext-devel
-Requires: libselinux >= 1.25.2-1
+### Globals ###
+%global includesubiddir %{_includedir}/shadow
+# Fail linking if there are undefined symbols.
+%global _ld_strict_symbol_defs 1
+
+### Patches ###
+
+### Dependencies ###
Requires: audit-libs >= 1.6.5
+Requires: libselinux >= 1.25.2-1
+Requires: pam-libs
Requires: setup
-Requires(pre): coreutils
-Requires(post): coreutils
-Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+### Build Dependencies ###
+BuildRequires: audit-libs-devel >= 1.6.5
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: bison
+BuildRequires: docbook-dtds
+BuildRequires: docbook-style-xsl
+BuildRequires: flex
+BuildRequires: gcc
+BuildRequires: gettext-devel
+BuildRequires: git
+BuildRequires: itstool
+BuildRequires: libacl-devel
+BuildRequires: libattr-devel
+BuildRequires: libcmocka-devel
+BuildRequires: libeconf-devel
+BuildRequires: libselinux-devel >= 1.25.2-1
+BuildRequires: libsemanage-devel
+BuildRequires: libtool
+BuildRequires: libxcrypt-devel
+BuildRequires: libxslt
+BuildRequires: make
+BuildRequires: pam
+BuildRequires: pam-devel
+
+### Provides ###
+Provides: shadow = %{epoch}:%{version}-%{release}
+Provides: passwd = 0.80-18
+Obsoletes: passwd <= 0.80-19
+
+%if "%{_sbindir}" == "%{_bindir}"
+# Compat symlinks for Requires in other packages.
+# We rely on filesystem to create the symlinks for us.
+Requires: filesystem(unmerged-sbin-symlinks)
+Provides: /usr/sbin/adduser
+Provides: /usr/sbin/useradd
+Provides: /usr/sbin/userdel
+Provides: /usr/sbin/usermod
+Provides: /usr/sbin/groupadd
+Provides: /usr/sbin/groupdel
+Provides: /usr/sbin/groupmod
+%endif
%description
The shadow-utils package includes the necessary programs for
@@ -58,141 +77,112 @@ programs for managing user and group accounts. The pwconv command
converts passwords to the shadow password format. The pwunconv command
unconverts shadow passwords and generates a passwd file (a standard
UNIX password file). The pwck command checks the integrity of password
-and shadow files. The lastlog command prints out the last login times
-for all users. The useradd, userdel, and usermod commands are used for
-managing user accounts. The groupadd, groupdel, and groupmod commands
-are used for managing group accounts.
+and shadow files. The useradd, userdel, and usermod commands are used
+for managing user accounts. The groupadd, groupdel, and groupmod
+commands are used for managing group accounts.
+
+
+### Subpackages ###
+%package subid
+Summary: A library to manage subordinate uid and gid ranges
+
+%description subid
+Utility library that provides a way to manage subid ranges.
+
+
+%package subid-devel
+Summary: Development package for shadow-utils-subid
+Requires: shadow-utils-subid = %{epoch}:%{version}-%{release}
+
+%description subid-devel
+Development files for shadow-utils-subid.
%prep
-%setup -q -n shadow-%{version}
-%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
-%patch17 -p1 -b .userdel
-%patch18 -p1 -b .id-alloc
-%patch19 -p1 -b .date-parsing
-%patch20 -p1 -b .ingroup
-%patch21 -p1 -b .move-home
-%patch22 -p1 -b .audit-update
-%patch23 -p1 -b .unlock
-%patch24 -p1 -b .no-lock-dos
-%patch25 -p1 -b .defs-chroot
-%patch26 -p1 -b .unexpire
-%patch27 -p1 -b .user-busy
+%autosetup -p 1 -S git -n shadow-4.20.0
iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8
cp -f doc/HOWTO.utf8 doc/HOWTO
cp -a %{SOURCE4} %{SOURCE5} .
-
-rm libmisc/getdate.c
-
-#rm po/*.gmo
-#rm po/stamp-po
-#aclocal
-#libtoolize --force
-#automake -a
-#autoconf
+cp -a %{SOURCE6} man/login.defs.d/HOME_MODE.xml
%build
-
-%ifarch sparc64
-#sparc64 need big PIE
-export CFLAGS="$RPM_OPT_FLAGS -fPIE"
-export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now"
-%else
-export CFLAGS="$RPM_OPT_FLAGS -fpie"
-export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now"
-%endif
-
+autoreconf
%configure \
- --enable-shadowgrp \
+ --disable-account-tools-setuid \
+ --enable-logind=no \
--enable-man \
+ --enable-shadowgrp \
+ --enable-shared \
--with-audit \
- --with-sha-crypt \
+ --with-bcrypt \
+ --with-group-name-max-length=32 \
+ --with-libpam \
--with-selinux \
+ --with-sha-crypt \
+ --with-yescrypt \
+ --without-libbsd \
--without-libcrack \
- --without-libpam \
- --disable-shared \
- --with-group-name-max-length=32
-make
+ --without-nscd \
+ --without-sssd
+%make_build
+
+%check
+make check
%install
-rm -rf $RPM_BUILD_ROOT
-make install DESTDIR=$RPM_BUILD_ROOT 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 0600 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/default/useradd
+%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 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/login.defs
+install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/default/useradd
+install -d -m 755 $RPM_BUILD_ROOT%{_pam_confdir}
+install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/chpasswd
+install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/newusers
+install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/passwd
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
+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
done
+%if "%{_sbindir}" == "%{_bindir}"
+# The installation script doesn't actually use the configured paths :(
+mv -v $RPM_BUILD_ROOT/usr/sbin/* $RPM_BUILD_ROOT%{_bindir}/
+%endif
+
# Remove binaries we don't use.
-rm $RPM_BUILD_ROOT/%{_bindir}/chfn
-rm $RPM_BUILD_ROOT/%{_bindir}/chsh
-rm $RPM_BUILD_ROOT/%{_bindir}/expiry
-rm $RPM_BUILD_ROOT/%{_bindir}/groups
-rm $RPM_BUILD_ROOT/%{_bindir}/login
-rm $RPM_BUILD_ROOT/%{_bindir}/passwd
-rm $RPM_BUILD_ROOT/%{_bindir}/su
-rm $RPM_BUILD_ROOT/%{_bindir}/faillog
-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.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/chsh.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man1/expiry.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/expiry.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man1/groups.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/groups.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man1/login.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/login.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man1/passwd.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/passwd.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man1/su.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/su.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man5/limits.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/limits.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man5/login.access.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/login.access.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man5/passwd.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/passwd.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man5/porttime.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/porttime.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man5/suauth.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/suauth.*
-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.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/faillog.*
-rm $RPM_BUILD_ROOT/%{_mandir}/man8/faillog.*
-rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/faillog.*
+rm $RPM_BUILD_ROOT%{_bindir}/chfn
+rm $RPM_BUILD_ROOT%{_bindir}/chsh
+rm $RPM_BUILD_ROOT%{_bindir}/login
+rm $RPM_BUILD_ROOT%{_bindir}/su
+rm $RPM_BUILD_ROOT%{_bindir}/faillog
+rm $RPM_BUILD_ROOT%{_sbindir}/nologin
+rm $RPM_BUILD_ROOT%{_mandir}/man1/chfn.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chfn.*
+rm $RPM_BUILD_ROOT%{_mandir}/man1/chsh.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chsh.*
+rm $RPM_BUILD_ROOT%{_mandir}/man1/login.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man1/login.*
+rm $RPM_BUILD_ROOT%{_mandir}/man1/su.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man1/su.*
+rm $RPM_BUILD_ROOT%{_mandir}/man5/passwd.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man5/passwd.*
+rm $RPM_BUILD_ROOT%{_mandir}/man8/nologin.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man8/nologin.*
+rm $RPM_BUILD_ROOT%{_mandir}/man3/getspnam.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man3/getspnam.*
+rm $RPM_BUILD_ROOT%{_mandir}/man5/faillog.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man5/faillog.*
+rm $RPM_BUILD_ROOT%{_mandir}/man8/faillog.*
+rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.*
+
+# Remove PAM service files we don't use.
+rm $RPM_BUILD_ROOT%{_pam_confdir}/chfn
+rm $RPM_BUILD_ROOT%{_pam_confdir}/chsh
+rm $RPM_BUILD_ROOT%{_pam_confdir}/login
+rm $RPM_BUILD_ROOT%{_pam_confdir}/su
find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete
%find_lang shadow
@@ -204,23 +194,30 @@ for dir in $(ls -1d $RPM_BUILD_ROOT%{_mandir}/{??,??_??}) ; do
echo "%%lang($lang) $dir/man*/*" >> shadow.lang
done
-%clean
-rm -rf $RPM_BUILD_ROOT
+# Move header files to its own folder
+echo $(ls)
+mkdir -p $RPM_BUILD_ROOT/%{includesubiddir}
+install -m 644 libsubid/subid.h $RPM_BUILD_ROOT/%{includesubiddir}/
+
+# Remove .la and .a files created by libsubid
+rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la
+rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a
%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
+%config(noreplace) %{_pam_confdir}/chpasswd
+%config(noreplace) %{_pam_confdir}/newusers
+%config(noreplace) %{_pam_confdir}/passwd
%{_bindir}/sg
%attr(4755,root,root) %{_bindir}/chage
%attr(4755,root,root) %{_bindir}/gpasswd
-%{_bindir}/lastlog
%attr(4755,root,root) %{_bindir}/newgrp
-%attr(4755,root,root) %{_bindir}/newgidmap
-%attr(4755,root,root) %{_bindir}/newuidmap
+%attr(0755,root,root) %caps(cap_setgid=ep) %{_bindir}/newgidmap
+%attr(0755,root,root) %caps(cap_setuid=ep) %{_bindir}/newuidmap
+%attr(4755,root,root) %{_bindir}/passwd
%{_sbindir}/adduser
%attr(0755,root,root) %{_sbindir}/user*
%attr(0755,root,root) %{_sbindir}/group*
@@ -228,6 +225,7 @@ rm -rf $RPM_BUILD_ROOT
%{_sbindir}/pwck
%{_sbindir}/*conv
%{_sbindir}/chpasswd
+%{_sbindir}/chgpasswd
%{_sbindir}/newusers
%{_sbindir}/vipw
%{_sbindir}/vigr
@@ -237,6 +235,7 @@ rm -rf $RPM_BUILD_ROOT
%{_mandir}/man1/newgrp.1*
%{_mandir}/man1/newgidmap.1*
%{_mandir}/man1/newuidmap.1*
+%{_mandir}/man1/passwd.*
%{_mandir}/man3/shadow.3*
%{_mandir}/man5/shadow.5*
%{_mandir}/man5/login.defs.5*
@@ -249,13 +248,479 @@ rm -rf $RPM_BUILD_ROOT
%{_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*
%{_mandir}/man8/vipw.8*
%{_mandir}/man8/vigr.8*
+%files subid
+%{_libdir}/libsubid.so.*
+%{_bindir}/getsubids
+%{_mandir}/man1/getsubids.1*
+
+%files subid-devel
+%{includesubiddir}/subid.h
+%{_libdir}/libsubid.so
+
%changelog
+* Wed Jul 29 2026 Iker Pedrosa - 2:4.20.0-1
+- Rebase to version 4.20.0
+
+* Wed Jul 22 2026 Iker Pedrosa - 2:4.20.0-rc3-1
+- Rebase to version 4.20.0-rc3
+
+* Fri Jul 17 2026 Fedora Release Engineering - 2:4.19.3-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
+
+* Wed May 27 2026 Iker Pedrosa - 2:4.19.3-3
+- Enable use of PAM for chpasswd and newusers
+ Resolves: #2461179 and #2283963
+
+* Thu Apr 23 2026 Iker Pedrosa - 2:4.19.3-2
+- btrfs: simplify checks improve useradd behavior for non-btrfs
+
+* Wed Feb 11 2026 Debarshi Ray - 2:4.19.3-1
+- Rebase to version 4.19.3
+ Resolves: #2426288
+
+* Tue Jan 27 2026 Adam Williamson - 2:4.19.0-6
+- chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 regexes
+
+* Mon Jan 26 2026 Iker Pedrosa - 2:4.19.0-5
+- chkhash.c: fix support for ! and * in hashes
+- usermod.c: add back optimizations
+
+* Sat Jan 17 2026 Fedora Release Engineering - 2:4.19.0-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild
+
+* Mon Jan 12 2026 Iker Pedrosa - 2:4.19.0-3
+- useradd: Support config for creating home dirs as Btrfs subvolumes
+
+* Fri Jan 9 2026 Iker Pedrosa - 2:4.19.0-2
+- Enable unit-tests
+
+* Fri Jan 9 2026 Iker Pedrosa - 2:4.19.0-1
+- Rebase to version 4.19.0
+ Resolves: #2426288 and #2249524
+
+* Tue Nov 25 2025 Adam Williamson - 2:4.18.0-7
+- Also revert changes from -4 (last known good was -3)
+
+* Tue Nov 25 2025 Adam Williamson - 2:4.18.0-6
+- Revert changes from -5 (they were only meant for testing)
+
+* Tue Nov 25 2025 Iker Pedrosa - 2:4.18.0-5
+- Test CI
+
+* Fri Oct 31 2025 Iker Pedrosa - 2:4.18.0-4
+- Stop setting SELinux labels in chroot and prefix environments
+ Resolves: #2249524
+
+* Tue Jul 29 2025 Alexey Tikhonov - 2:4.18.0-3
+- Revert "Stop assigning subids by default"
+ Resolves: #2382662
+
+* Fri Jul 25 2025 Fedora Release Engineering - 2:4.18.0-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
+
+* Tue Jul 22 2025 Iker Pedrosa - 2:4.18.0-1
+- Rebase to version 4.18.0. Resolves: #2374710
+
+* Fri Jul 18 2025 Iker Pedrosa - 2:4.17.4-5
+- Stop assigning subids by default
+ Resolves: CVE-2024-56433 and #2334168
+
+* Tue Jul 15 2025 Iker Pedrosa - 2:4.17.4-4
+- FSWC: Migrate to lastlog2
+ Link:
+ Resolves: #2361588
+
+* Tue Mar 25 2025 Iker Pedrosa - 2:4.17.4-2
+- Add pam dependency for _pam_confdir missing macro. Resolves: #2354806
+
+* Thu Mar 20 2025 Iker Pedrosa - 2:4.17.4-1
+- Rebase to version 4.17.4. Resolves: #2353491
+- Fixes problems with expiration dates
+
+* Sat Feb 01 2025 Björn Esser - 2:4.17.0-5
+- Add explicit BR: libxcrypt-devel
+
+* Sun Jan 19 2025 Fedora Release Engineering - 2:4.17.0-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
+
+* Sun Jan 12 2025 Zbigniew Jędrzejewski-Szmek - 2:4.17.0-3
+- Rebuilt for the bin-sbin merge (2nd attempt)
+
+* Thu Dec 26 2024 Iker Pedrosa - 2:4.17.0
+- Rebase to version 4.17.0. Resolves: #2293678
+
+* Sun Dec 22 2024 Björn Esser - 2:4.17.0~rc1-2
+- Remove potentially dangerous {C,LD}FLAGS shenanigans
+- Fail linking if there are undefined symbols at link-time
+
+* Mon Dec 9 2024 Iker Pedrosa - 2:4.17.0~rc1-1
+- Rebase to version 4.17.0-rc1
+
+* Tue Nov 12 2024 Iker Pedrosa - 2:4.16.0-7
+- SPDX license migration for subpackages
+
+* Wed Oct 16 2024 Iker Pedrosa - 2:4.16.0-6
+- Rebuilt for libeconf soname bump
+
+* Mon Oct 7 2024 Iker Pedrosa - 2:4.16.0-5
+- useradd: fix write_full() return value. Resolves: #2313559
+
+* Fri Sep 13 2024 Iker Pedrosa - 2:4.16.0-3
+- Disable nscd
+
+* Wed Aug 28 2024 Iker Pedrosa - 2:4.16.0-2
+- Rebase to version 4.16.0 (#2293678)
+
+* Tue Jul 23 2024 Kevin Fenzi - 2:4.15.1-9
+- Revert chpasswd: use PAM again for now.
+
+* Sat Jul 20 2024 Fedora Release Engineering - 2:4.15.1-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
+
+* Tue Jul 09 2024 Zbigniew Jędrzejewski-Szmek - 2:4.15.1-7
+- Rebuilt for the bin-sbin merge
+
+* Thu May 30 2024 Iker Pedrosa - 2:4.15.1-6
+- chpasswd: use PAM again (#2283963)
+
+* Mon May 20 2024 Iker Pedrosa - 2:4.15.1-5
+- Several fixes for issues detected by static analyzer tools
+
+* Thu Apr 11 2024 Zbigniew Jedrzejewski-Szmek - 2:4.15.1-4
+- Fix build with %%_bindir==%%_sbindir
+- Add virtual Provides for old file paths used by other packages
+
+* Thu Mar 21 2024 Iker Pedrosa - 2:4.15.1-2
+- getdef: avoid spurious error messages about unknown configuration options.
+ Resolves: #2265291
+
+* Tue Mar 12 2024 Iker Pedrosa - 2:4.15.1-1
+- Wrong versioning for 4.15.0 RC releases makes the oficial release look lower than them.
+ Fix it by bumping the minor release to 4.15.1. Resolves: #2268690
+
+* Mon Mar 11 2024 Iker Pedrosa - 2:4.15.0-1
+- Rebase to version 4.15.0
+
+* Mon Feb 12 2024 Iker Pedrosa - 2:4.14.0-6
+- Build linking `libpam`
+
+* Thu Feb 1 2024 Iker Pedrosa - 2:4.14.0-5
+- passwd: Provide binary from this package. Enable libpam and
+ disable account-tools-setuid. Provide passwd PAM service file.
+ Resolves: #2233275
+- passwd: provide --stdin option
+
+* Mon Jan 29 2024 Iker Pedrosa - 2:4.14.0-4
+- Disable SSSD support. Resolves: #2253182
+
+* Sat Jan 27 2024 Fedora Release Engineering - 2:4.14.0-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
+
+* Tue Oct 3 2023 Iker Pedrosa - 2:4.14.0-2
+- useradd: Set proper SELinux labels for def_usrtemplate
+
+* Wed Aug 16 2023 Iker Pedrosa - 2:4.14.0-1
+- Rebase to version 4.14.0. Resolves: #2229000
+
+* Sat Jul 22 2023 Fedora Release Engineering - 2:4.13-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
+
+* Tue Jun 06 2023 Yaakov Selkowitz - 2:4.13-7
+- Remove unused libbsd-devel dependency
+
+* Mon Mar 6 2023 Iker Pedrosa - 2:4.13-6
+- Add libbsd-devel and libeconf-devel as build dependencies
+
+* Thu Mar 2 2023 Iker Pedrosa - 2:4.13-5
+- newuidmap and newgidmap: support passing pid as fd. Resolves: #2174752
+
+* Sat Jan 21 2023 Fedora Release Engineering - 2:4.13-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
+
+* Wed Nov 23 2022 Iker Pedrosa - 2:4.13-3
+- Change SUB_UID_MIN and SUB_GID_MIN to 524288. Resolves: #2144558
+
+* Mon Nov 21 2022 Florian Weimer - 2:4.13-2
+- Fix gshadow configure check (switching to glibc implementation)
+
+* Wed Nov 9 2022 Iker Pedrosa - 2:4.13-1
+- Rebase to version 4.13
+- SPDX license migration
+
+* Wed Oct 5 2022 Iker Pedrosa - 2:4.12.3-3
+- chage: Fix regression in print_date. Resolves: #2129336
+
+* Fri Sep 9 2022 Iker Pedrosa - 2:4.12.3-2
+- useradd: Do not reset non-existent data in {last,fail}log
+
+* Mon Aug 22 2022 Iker Pedrosa - 2:4.12.3-1
+- Rebase to version 4.12.3. Resolves: #2117809
+
+* Mon Aug 1 2022 Iker Pedrosa - 2:4.11.1-4
+- useradd: modify check ID range for system users. Resolves: #2093692
+
+* Sat Jul 23 2022 Fedora Release Engineering - 2:4.11.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
+
+* Thu Feb 10 2022 Iker Pedrosa - 2:4.11.1-2
+- Fix explicit subid requirement for subid-devel
+
+* Tue Jan 25 2022 Iker Pedrosa - 2:4.11.1-1
+- Rebase to version 4.11.1 (#2034038)
+- Fix release sources
+- Add explicit subid requirement for subid-devel
+
+* Sat Jan 22 2022 Fedora Release Engineering - 2:4.9-10
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
+
+* Mon Jan 17 2022 Iker Pedrosa - 2:4.9-9
+- nss: get shadow_logfd with log_get_logfd() (#2038811)
+- lib: make shadow_logfd and Prog not extern
+- lib: rename Prog to shadow_progname
+- lib: provide default values for shadow_progname
+- libsubid: use log_set_progname in subid_init
+
+* Fri Nov 19 2021 Iker Pedrosa - 2:4.9-8
+- getsubids: provide system binary and man page (#1980780)
+- pwck: fix segfault when calling fprintf() (#2021339)
+- newgrp: fix segmentation fault (#2019553)
+- groupdel: fix SIGSEGV when passwd does not exist (#1986111)
+
+* Fri Nov 12 2021 Iker Pedrosa - 2:4.9-7
+- useradd: change SELinux labels for home files (#2022658)
+
+* Thu Nov 4 2021 Iker Pedrosa - 2:4.9-6
+- useradd: revert fix memleak of grp (#2018697)
+
+* Wed Oct 27 2021 Iker Pedrosa - 2:4.9-5
+- useradd: generate home and mail directories with selinux user attribute
+
+* Thu Sep 23 2021 Iker Pedrosa - 2:4.9-4
+- login.defs: include HMAC_CRYPTO_ALGO key
+- Clean spec file: organize dependencies and move License location
+
+* Tue Aug 17 2021 Iker Pedrosa - 2:4.9-3
+- libmisc: fix default value in SHA_get_salt_rounds()
+
+* Mon Aug 9 2021 Iker Pedrosa - 2:4.9-2
+- useradd: avoid generating an empty subid range (#1990653)
+
+* Wed Aug 4 2021 Iker Pedrosa - 2:4.9-1
+- Rebase to version 4.9
+- usermod: allow all group types with -G option (#1975327)
+- Clean spec file
+
+* Fri Jul 23 2021 Fedora Release Engineering - 2:4.8.1-20
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
+
+* Wed Jul 14 2021 Björn Esser - 2:4.8.1-19
+- Add patch to fix 'fread returns element count, not element size'
+
+* Wed Jul 14 2021 Iker Pedrosa - 2:4.8.1-18
+- Fix regression issues detected in rhbz#667593 and rhbz#672510
+
+* Mon Jul 12 2021 Björn Esser - 2:4.8.1-17
+- Enable bcrypt support, as libxcrypt supports it well
+
+* Sun Jul 04 2021 Björn Esser - 2:4.8.1-16
+- Add a patch to obtain random bytes using getentropy()
+- Update shadow-4.8-crypt_h.patch with the upstreamed version
+- Add a patch to make use of crypt_gensalt() from libxcrypt
+
+* Tue Jun 29 2021 Iker Pedrosa - 2:4.8.1-15
+- useradd: free correct pointer (#1976809)
+
+* Mon Jun 28 2021 Björn Esser - 2:4.8.1-14
+- Add a patch to fix the used prefix for the bcrypt hash method
+- Add a patch to cleanup the code in libmisc/salt.c
+- Add a patch adding some clarifying comments in libmisc/salt.c
+- Add a patch to obtain random bytes from /dev/urandom
+
+* Mon Jun 28 2021 Iker Pedrosa - 2:4.8.1-13
+- Covscan fixes
+
+* Mon Jun 21 2021 Björn Esser - 2:4.8.1-12
+- Backport support for yescrypt hash method
+- Add a patch to fix the parameter type of YESCRYPT_salt_cost()
+
+* Mon Jun 21 2021 Iker Pedrosa - 2:4.8.1-11
+- libsubid: don't print error messages on stderr by default
+- libsubid: libsubid_init return false if out of memory
+- useradd: fix SUB_UID_COUNT=0
+- libsubid: don't return owner in list_owner_ranges API call
+- libsubid: libsubid_init don't print messages on error
+- libsubid: fix newusers when nss provides subids
+- man: clarify subid delegation
+- libsubid: make shadow_logfd not extern
+
+* Thu May 6 2021 Iker Pedrosa - 2:4.8.1-10
+- man: mention NSS in new[ug]idmap manpages
+- libsubid: move development header to shadow folder
+
+* Fri Apr 16 2021 Iker Pedrosa - 2:4.8.1-9
+- libsubid: creation and nsswitch support
+- Creation of subid and subid-devel subpackages
+
+* Mon Mar 29 2021 Iker Pedrosa - 2:4.8.1-8
+- man: include lastlog file caveat (#951564)
+- Upstream links to several patches
+- Spec file cleanup by Robert Scheck
+- Add BuildRequires: make by Tom Stellard
+
+* Wed Jan 27 2021 Fedora Release Engineering - 2:4.8.1-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Mon Nov 9 2020 Iker Pedrosa - 2:4.8.1-6
+- commonio: force lock file sync (#1862056)
+
+* Tue Nov 3 2020 Petr Lautrbach - 2:4.8.1-5
+- Rebuild with libsemanage.so.2
+
+* Wed Jul 29 2020 Fedora Release Engineering - 2:4.8.1-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Thu May 14 2020 Iker Pedrosa - 2:4.8.1-3
+- check only local groups when adding new supplementary groups to a user (#1727236)
+
+* Tue Mar 24 2020 Iker Pedrosa - 2:4.8.1-2
+- useradd: clarify the useradd -d parameter behavior in man page
+
+* Tue Mar 17 2020 Iker Pedrosa - 2:4.8.1-1
+- updated upstream to 4.8.1
+
+* Tue Mar 17 2020 Iker Pedrosa - 2:4.8-5
+- synchronized login.defs with upstream file (#1261099 and #1807957)
+
+* Mon Feb 24 2020 Iker Pedrosa - 2:4.8-4
+- fix useradd: doesn't generate spool mail with the proper SELinux user identity
+ (#1690527)
+
+* Thu Jan 30 2020 Fedora Release Engineering - 2:4.8-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Thu Jan 16 2020 Tomáš Mráz - 2:4.8-2
+- make the invalid shell check into warning
+
+* Mon Jan 13 2020 Tomáš Mráz - 2:4.8-1
+- update to current upstream release 4.8
+
+* Mon Sep 2 2019 Tomáš Mráz - 2:4.6-16
+- fix SELinux related problem in chpasswd/chgpasswd when run with -R
+ (patch by Petr Lautrbach) (#1747215)
+
+* Fri Jul 26 2019 Fedora Release Engineering - 2:4.6-15
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Fri Jun 7 2019 Tomáš Mráz - 2:4.6-14
+- minor auditing fixes
+
+* Fri May 3 2019 Tomáš Mráz - 2:4.6-13
+- use lckpwdf() again to disable concurrent edits of databases by
+ other applications
+
+* Tue Apr 2 2019 Tomáš Mráz - 2:4.6-12
+- force regeneration of getdate.c otherwise the date parsing fix
+ is not applied
+
+* Fri Mar 22 2019 Tomáš Mráz - 2:4.6-11
+- clarify chage manual page in regards to shadow and passwd
+ inconsistency (#1686440)
+
+* Thu Mar 21 2019 Tomáš Mráz - 2:4.6-10
+- Ignore LOGIN_PLAIN_PROMPT variable in login.defs
+
+* Thu Mar 7 2019 Tim Landscheidt - 2:4.6-9
+- Remove obsolete requirements for post/pre scriptlets
+
+* Sat Feb 02 2019 Fedora Release Engineering - 2:4.6-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Mon Jan 14 2019 Björn Esser - 2:4.6-7
+- Rebuilt for libcrypt.so.2 (#1666033)
+
+* Tue Dec 18 2018 Tomáš Mráz - 2:4.6-6
+- usermod: guard against unsafe change of ownership of
+ special home directories
+
+* Mon Nov 19 2018 Tomáš Mráz - 2:4.6-5
+- use itstool instead of xml2po
+
+* Tue Nov 6 2018 Tomáš Mráz - 2:4.6-4
+- use cap_setxid file capabilities for newxidmap instead of making them setuid
+- limit the SYS_U/GID_MIN value to 1 as the algorithm does not work with 0
+ and the 0 is always used by root anyway
+- manual page improvements
+
+* Wed Oct 10 2018 Tomáš Mráz - 2:4.6-3
+- fix some issues from Coverity scan
+- flush sssd caches - patch by Jakub Hrozek
+
+* Sat Jul 14 2018 Fedora Release Engineering - 2:4.6-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Mon May 28 2018 Tomáš Mráz - 2:4.6-1
+- update to current upstream release 4.6
+
+* Fri Apr 20 2018 Tomáš Mráz - 2:4.5-10
+- Raise limit for passwd and shadow entry length but also prevent
+ writing longer entries (#1422497)
+
+* Tue Feb 06 2018 Björn Esser - 2:4.5-9
+- Add patch to include crypt.h, if present
+- Use %%make_{build,install} macros
+- Refresh other patches for proper alignment
+
+* Sat Jan 20 2018 Björn Esser - 2:4.5-8
+- Rebuilt for switch to libxcrypt
+
+* Mon Nov 6 2017 Tomáš Mráz - 2:4.5-7
+- fix regression caused by the userdel-chroot patch (#1509978)
+
+* Thu Nov 2 2017 Tomáš Mráz - 2:4.5-6
+- fix userdel in chroot (#1316168)
+- add useful chage -E example to chage manpage
+
+* Fri Sep 15 2017 Tomáš Mráz - 2:4.5-5
+- do not allow "." and ".." user names
+
+* Mon Aug 14 2017 Tomáš Mráz - 2:4.5-4
+- allow switching to secondary group without checking the membership
+ explicitly (patch from upstream)
+
+* Thu Aug 03 2017 Fedora Release Engineering - 2:4.5-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Thu Jul 27 2017 Fedora Release Engineering - 2:4.5-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Fri Jul 21 2017 Tomáš Mráz - 2:4.5-1
+- update to current upstream release 4.5
+
+* Sat Feb 11 2017 Fedora Release Engineering - 2:4.3.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Thu Aug 25 2016 Tomáš Mráz - 2:4.3.1-2
+- fix regression in useradd - not processing defaults properly (#1369979)
+
+* Tue Aug 23 2016 Tomáš Mráz - 2:4.3.1-1
+- new upstream release fixing low impact security issue
+
+* Tue Jun 14 2016 Tomáš Mráz - 2:4.2.1-11
+- guard for localtime() and gmtime() failure
+
+* Mon May 30 2016 Tomáš Mráz - 2:4.2.1-10
+- chpasswd, chgpasswd: open audit when starting
+
+* Thu May 26 2016 Tomáš Mráz - 2:4.2.1-9
+- chgpasswd: do not remove it
+- chpasswd, chgpasswd: add selinux_check_access call (#1336902)
+
* Thu Mar 17 2016 Tomáš Mráz - 2:4.2.1-8
- userdel: fix userdel -f with /etc/subuid present (#1316168)
diff --git a/sources b/sources
index 9a96021..7669083 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
-2bfafe7d4962682d31b5eba65dba4fc8 shadow-4.2.1.tar.xz
-6752051fb07fc4be58c3d7b929bf2341 shadow-4.2.1.tar.xz.sig
+SHA512 (shadow-4.20.0.tar.xz) = 0b8afded372e4d37a78f38cb972c0ab877870ef6356cdd1c45be3c708af3d1496c6f87de6bf6a5b1d217d4d52d7e2d15c28b26530949cc6de0231a4028930406
+SHA512 (shadow-4.20.0.tar.xz.asc) = e4b134543768f323df30a1e450c22086d013020928d62bd3207db7f633beea3587b67802da5b575d5a794e8c2bebd7a0abeba6ed69d44bf08adc37df3bf352ac
diff --git a/tests/mhc-fedora-ci.yaml b/tests/mhc-fedora-ci.yaml
new file mode 100644
index 0000000..8747e67
--- /dev/null
+++ b/tests/mhc-fedora-ci.yaml
@@ -0,0 +1,13 @@
+provisioned_topologies:
+- shadow
+domains:
+- id: shadow
+ hosts:
+ - hostname: localhost
+ role: shadow
+ conn:
+ type: ssh
+ host: localhost
+ user: root
+ artifacts:
+ - /var/log/*