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 5db8705..3023995 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,25 @@ shadow-4.1.4.2.tar.bz2 /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/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.13-newidmap-support-passing-pid-as-fd.patch b/shadow-4.13-newidmap-support-passing-pid-as-fd.patch deleted file mode 100644 index 37e0d41..0000000 --- a/shadow-4.13-newidmap-support-passing-pid-as-fd.patch +++ /dev/null @@ -1,441 +0,0 @@ -From 6974df39a708abf8bafbdfa2b7827e0f70f874cb Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Mon, 6 Feb 2023 22:49:42 -0600 -Subject: [PATCH] newuidmap and newgidmap: support passing pid as fd - -Closes #635 - -newuidmap and newgidmap currently take an integner pid as -the first argument, determining the process id on which to -act. Accept also "fd:N", where N must be an open file -descriptor to the /proc/pid directory for the process to -act upon. This way, if you - -exec 10 ---- - lib/get_pid.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ - lib/prototypes.h | 2 ++ - man/newgidmap.1.xml | 11 ++++++++++ - man/newuidmap.1.xml | 11 ++++++++++ - src/newgidmap.c | 41 ++++++++++++++---------------------- - src/newuidmap.c | 40 +++++++++++++---------------------- - 6 files changed, 106 insertions(+), 50 deletions(-) - -diff --git a/lib/get_pid.c b/lib/get_pid.c -index 10184bf0..ab91d158 100644 ---- a/lib/get_pid.c -+++ b/lib/get_pid.c -@@ -10,6 +10,9 @@ - - #include "prototypes.h" - #include "defines.h" -+#include -+#include -+#include - - int get_pid (const char *pidstr, pid_t *pid) - { -@@ -29,3 +32,51 @@ int get_pid (const char *pidstr, pid_t *pid) - return 1; - } - -+/* -+ * If use passed in fd:4 as an argument, then return the -+ * value '4', the fd to use. -+ */ -+int get_pidfd_from_fd(const char *pidfdstr) -+{ -+ long long int val; -+ char *endptr; -+ -+ errno = 0; -+ val = strtoll (pidfdstr, &endptr, 10); -+ if ( ('\0' == *pidfdstr) -+ || ('\0' != *endptr) -+ || (ERANGE == errno) -+ || (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) { -+ return 0; -+ } -+ -+ return (int)val; -+} -+ -+int open_pidfd(const char *pidstr) -+{ -+ int proc_dir_fd; -+ int written; -+ char proc_dir_name[32]; -+ pid_t target; -+ -+ if (get_pid(pidstr, &target) == 0) -+ return -ENOENT; -+ -+ /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ -+ written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", -+ target); -+ if ((written <= 0) || ((size_t)written >= sizeof(proc_dir_name))) { -+ fprintf(stderr, "snprintf of proc path failed for %u: %s\n", -+ target, strerror(errno)); -+ return -EINVAL; -+ } -+ -+ proc_dir_fd = open(proc_dir_name, O_DIRECTORY); -+ if (proc_dir_fd < 0) { -+ fprintf(stderr, _("Could not open proc directory for target %u: %s\n"), -+ target, strerror(errno)); -+ return -EINVAL; -+ } -+ return proc_dir_fd; -+} -diff --git a/lib/prototypes.h b/lib/prototypes.h -index 400d5b97..21df6f61 100644 ---- a/lib/prototypes.h -+++ b/lib/prototypes.h -@@ -160,6 +160,8 @@ extern int getlong (const char *numstr, /*@out@*/long int *result); - - /* get_pid.c */ - extern int get_pid (const char *pidstr, pid_t *pid); -+extern int get_pidfd_from_fd(const char *pidfdstr); -+extern int open_pidfd(const char *pidstr); - - /* getrange */ - extern int getrange (const char *range, -diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml -index e4ebc69e..9b7683eb 100644 ---- a/man/newgidmap.1.xml -+++ b/man/newgidmap.1.xml -@@ -116,6 +116,17 @@ - - Note that newgidmap may be used only once for a given process. - -+ -+ Instead of an integer process id, the first argument may be -+ specified as fd:N, where the integer N -+ is the file descriptor number for the calling process's opened -+ file for /proc/[pid[. In this case, -+ newgidmap will use -+ openat2 -+ to open the gid_map file under that -+ directory, avoiding a TOCTTOU in case the process exits and -+ the pid is immediately reused. -+ - - - -diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml -index f5cb5b48..ca917a77 100644 ---- a/man/newuidmap.1.xml -+++ b/man/newuidmap.1.xml -@@ -116,6 +116,17 @@ - - Note that newuidmap may be used only once for a given process. - -+ -+ Instead of an integer process id, the first argument may be -+ specified as fd:N, where the integer N -+ is the file descriptor number for the calling process's opened -+ file for /proc/[pid[. In this case, -+ newuidmap will use -+ openat2 -+ to open the uid_map file under that -+ directory, avoiding a TOCTTOU in case the process exits and -+ the pid is immediately reused. -+ - - - -diff --git a/src/newgidmap.c b/src/newgidmap.c -index 01d0fe90..d6d29725 100644 ---- a/src/newgidmap.c -+++ b/src/newgidmap.c -@@ -69,7 +69,7 @@ static void verify_ranges(struct passwd *pw, int ranges, - - static void usage(void) - { -- fprintf(stderr, _("usage: %s [ ] ... \n"), Prog); -+ fprintf(stderr, _("usage: %s [] [ ] ... \n"), Prog); - exit(EXIT_FAILURE); - } - -@@ -143,15 +143,12 @@ out: - */ - int main(int argc, char **argv) - { -- char proc_dir_name[32]; - char *target_str; -- pid_t target; - int proc_dir_fd; - int ranges; - struct map_range *mappings; - struct stat st; - struct passwd *pw; -- int written; - bool allow_setgroups = false; - - Prog = Basename (argv[0]); -@@ -168,25 +165,19 @@ int main(int argc, char **argv) - /* Find the process that needs its user namespace - * gid mapping set. - */ -- target_str = argv[1]; -- if (!get_pid(target_str, &target)) -- usage(); - -- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ -- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", -- target); -- if ((written <= 0) || (written >= sizeof(proc_dir_name))) { -- fprintf(stderr, "%s: snprintf of proc path failed: %s\n", -- Prog, strerror(errno)); -- } -- -- proc_dir_fd = open(proc_dir_name, O_DIRECTORY); -- if (proc_dir_fd < 0) { -- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"), -- Prog, target); -- return EXIT_FAILURE; -+ target_str = argv[1]; -+ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) { -+ /* the user passed in a /proc/pid fd for the process */ -+ target_str = &target_str[3]; -+ proc_dir_fd = get_pidfd_from_fd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); -+ } else { -+ proc_dir_fd = open_pidfd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); - } -- - /* Who am i? */ - pw = get_my_pwent (); - if (NULL == pw) { -@@ -200,8 +191,8 @@ int main(int argc, char **argv) - - /* Get the effective uid and effective gid of the target process */ - if (fstat(proc_dir_fd, &st) < 0) { -- fprintf(stderr, _("%s: Could not stat directory for target %u\n"), -- Prog, target); -+ fprintf(stderr, _("%s: Could not stat directory for process\n"), -+ Prog); - return EXIT_FAILURE; - } - -@@ -213,8 +204,8 @@ int main(int argc, char **argv) - (!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) || - (pw->pw_uid != st.st_uid) || - (getgid() != st.st_gid)) { -- fprintf(stderr, _( "%s: Target %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -- Prog, target, -+ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -+ Prog, - (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid, - (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid); - return EXIT_FAILURE; -diff --git a/src/newuidmap.c b/src/newuidmap.c -index e8798409..e99655c9 100644 ---- a/src/newuidmap.c -+++ b/src/newuidmap.c -@@ -64,7 +64,7 @@ static void verify_ranges(struct passwd *pw, int ranges, - - static void usage(void) - { -- fprintf(stderr, _("usage: %s [ ] ... \n"), Prog); -+ fprintf(stderr, _("usage: %s [|fd:] [ ] ... \n"), Prog); - exit(EXIT_FAILURE); - } - -@@ -73,15 +73,12 @@ static void usage(void) - */ - int main(int argc, char **argv) - { -- char proc_dir_name[32]; - char *target_str; -- pid_t target; - int proc_dir_fd; - int ranges; - struct map_range *mappings; - struct stat st; - struct passwd *pw; -- int written; - - Prog = Basename (argv[0]); - log_set_progname(Prog); -@@ -94,26 +91,20 @@ int main(int argc, char **argv) - if (argc < 2) - usage(); - -+ target_str = argv[1]; - /* Find the process that needs its user namespace - * uid mapping set. - */ -- target_str = argv[1]; -- if (!get_pid(target_str, &target)) -- usage(); -- -- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ -- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", -- target); -- if ((written <= 0) || (written >= sizeof(proc_dir_name))) { -- fprintf(stderr, "%s: snprintf of proc path failed: %s\n", -- Prog, strerror(errno)); -- } -- -- proc_dir_fd = open(proc_dir_name, O_DIRECTORY); -- if (proc_dir_fd < 0) { -- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"), -- Prog, target); -- return EXIT_FAILURE; -+ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) { -+ /* the user passed in a /proc/pid fd for the process */ -+ target_str = &target_str[3]; -+ proc_dir_fd = get_pidfd_from_fd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); -+ } else { -+ proc_dir_fd = open_pidfd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); - } - - /* Who am i? */ -@@ -129,8 +120,7 @@ int main(int argc, char **argv) - - /* Get the effective uid and effective gid of the target process */ - if (fstat(proc_dir_fd, &st) < 0) { -- fprintf(stderr, _("%s: Could not stat directory for target %u\n"), -- Prog, target); -+ fprintf(stderr, _("%s: Could not stat directory for target process\n"), Prog); - return EXIT_FAILURE; - } - -@@ -142,8 +132,8 @@ int main(int argc, char **argv) - (!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) || - (pw->pw_uid != st.st_uid) || - (getgid() != st.st_gid)) { -- fprintf(stderr, _( "%s: Target process %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -- Prog, target, -+ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -+ Prog, - (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid, - (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid); - return EXIT_FAILURE; --- -2.39.2 - -From 7ff33fae6f9cd79c0e012671c37a172e9a681d0b Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Fri, 24 Feb 2023 13:52:32 -0600 -Subject: [PATCH] get_pidfd_from_fd: return -1 on error, not 0 - -Fixes: 6974df39a: newuidmap and newgidmap: support passing pid as fd -Signed-off-by: Serge Hallyn ---- - lib/get_pid.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/lib/get_pid.c b/lib/get_pid.c -index ab91d158..5b6d9da4 100644 ---- a/lib/get_pid.c -+++ b/lib/get_pid.c -@@ -35,6 +35,7 @@ int get_pid (const char *pidstr, pid_t *pid) - /* - * If use passed in fd:4 as an argument, then return the - * value '4', the fd to use. -+ * On error, return -1. - */ - int get_pidfd_from_fd(const char *pidfdstr) - { -@@ -47,7 +48,7 @@ int get_pidfd_from_fd(const char *pidfdstr) - || ('\0' != *endptr) - || (ERANGE == errno) - || (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) { -- return 0; -+ return -1; - } - - return (int)val; --- -2.39.2 - -From 05e2adf509ba0e3779dae66a276b86927a8e1e0e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Vin=C3=ADcius=20dos=20Santos=20Oliveira?= - -Date: Fri, 24 Feb 2023 18:06:02 -0300 -Subject: [PATCH] Validate fds created by the user - -write_mapping() will do the following: - -openat(proc_dir_fd, map_file, O_WRONLY); - -An attacker could create a directory containing a symlink named -"uid_map" pointing to any file owned by root, and thus allow him to -overwrite any root-owned file. ---- - lib/get_pid.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/lib/get_pid.c b/lib/get_pid.c -index 5b6d9da4..8e5e6014 100644 ---- a/lib/get_pid.c -+++ b/lib/get_pid.c -@@ -41,6 +41,8 @@ int get_pidfd_from_fd(const char *pidfdstr) - { - long long int val; - char *endptr; -+ struct stat st; -+ dev_t proc_st_dev, proc_st_rdev; - - errno = 0; - val = strtoll (pidfdstr, &endptr, 10); -@@ -51,6 +53,21 @@ int get_pidfd_from_fd(const char *pidfdstr) - return -1; - } - -+ if (stat("/proc/self/uid_map", &st) < 0) { -+ return -1; -+ } -+ -+ proc_st_dev = st.st_dev; -+ proc_st_rdev = st.st_rdev; -+ -+ if (fstat(val, &st) < 0) { -+ return -1; -+ } -+ -+ if (st.st_dev != proc_st_dev || st.st_rdev != proc_st_rdev) { -+ return -1; -+ } -+ - return (int)val; - } - --- -2.39.2 - diff --git a/shadow-4.15.0-account-tools-setuid.patch b/shadow-4.15.0-account-tools-setuid.patch deleted file mode 100644 index d162487..0000000 --- a/shadow-4.15.0-account-tools-setuid.patch +++ /dev/null @@ -1,380 +0,0 @@ -diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chpasswd.c ---- shadow-4.15.0/src/chpasswd.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/chpasswd.c 2024-03-11 11:21:57.561150382 +0100 -@@ -443,9 +443,11 @@ int main (int argc, char **argv) - char *cp; - const char *salt; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - bool use_pam = true; - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - int errors = 0; - int line = 0; -@@ -469,19 +471,23 @@ int main (int argc, char **argv) - process_root_flag ("-R", argc, argv); - prefix = process_prefix_flag ("-P", argc, argv); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (md5flg || eflg || cflg || prefix[0]) { - use_pam = false; - } - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - OPENLOG (Prog); - - check_perms (); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - is_shadow_pwd = spw_file_present (); - -@@ -543,6 +549,7 @@ int main (int argc, char **argv) - } - newpwd = cp; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (use_pam) { - if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { -@@ -553,6 +560,7 @@ int main (int argc, char **argv) - } - } else - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - const struct spwd *sp; - struct spwd newsp; -@@ -672,9 +680,11 @@ int main (int argc, char **argv) - * password database. - */ - if (0 != errors) { -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - fprintf (stderr, - _("%s: error detected, changes ignored\n"), -@@ -683,9 +693,11 @@ int main (int argc, char **argv) - fail_exit (1); - } - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - /* Save the changes */ - close_files (); -diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/groupmems.c ---- shadow-4.15.0/src/groupmems.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/groupmems.c 2024-03-11 11:16:18.365408572 +0100 -@@ -14,9 +14,11 @@ - #include - #include - #include -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - #include "pam_defs.h" - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - #include - - #include "alloc.h" -@@ -430,6 +432,7 @@ static void process_flags (int argc, cha - static void check_perms (void) - { - if (!list) { -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - pam_handle_t *pamh = NULL; - int retval; -@@ -463,7 +466,8 @@ static void check_perms (void) - fail_exit (1); - } - (void) pam_end (pamh, retval); --#endif -+#endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - } - } - -diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/newusers.c ---- shadow-4.15.0/src/newusers.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/newusers.c 2024-03-11 11:20:07.198909046 +0100 -@@ -59,6 +59,7 @@ - static const char Prog[] = "newusers"; - - static bool rflg = false; /* create a system account */ -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - static /*@null@*//*@observer@*/char *crypt_method = NULL; - #define cflg (NULL != crypt_method) -@@ -75,6 +76,7 @@ static long bcrypt_rounds = 13; - static long yescrypt_cost = 5; - #endif /* USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - - static bool is_shadow; - #ifdef SHADOWGRP -@@ -97,9 +99,11 @@ NORETURN static void fail_exit (int); - static int add_group (const char *, const char *, gid_t *, gid_t); - static int get_user_id (const char *, uid_t *); - static int add_user (const char *, uid_t, gid_t); -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - static int update_passwd (struct passwd *, const char *); - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - static int add_passwd (struct passwd *, const char *); - static void process_flags (int argc, char **argv); - static void check_flags (void); -@@ -121,6 +125,7 @@ static void usage (int status) - "Options:\n"), - Prog); - (void) fputs (_(" -b, --badname allow bad names\n"), usageout); -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - (void) fprintf (usageout, - _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -@@ -136,9 +141,11 @@ static void usage (int status) - #endif - ); - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); - (void) fputs (_(" -r, --system create system accounts\n"), usageout); - (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -@@ -146,6 +153,7 @@ static void usage (int status) - usageout); - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - (void) fputs ("\n", usageout); - - exit (status); -@@ -405,6 +413,7 @@ static int add_user (const char *name, u - return (pw_update (&pwent) == 0) ? -1 : 0; - } - -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - /* - * update_passwd - update the password in the passwd entry -@@ -457,6 +466,7 @@ static int update_passwd (struct passwd - return 0; - } - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - - /* - * add_passwd - add or update the encrypted password -@@ -465,10 +475,13 @@ static int add_passwd (struct passwd *pw - { - const struct spwd *sp; - struct spwd spent; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - char *cp; - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - void *crypt_arg = NULL; - if (NULL != crypt_method) { -@@ -505,13 +518,14 @@ static int add_passwd (struct passwd *pw - return update_passwd (pwd, password); - } - #endif /* USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - - /* - * Do the first and easiest shadow file case. The user already - * exists in the shadow password file. - */ - sp = spw_locate (pwd->pw_name); --#ifndef USE_PAM -+#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - if (NULL != sp) { - spent = *sp; - if ( (NULL != crypt_method) -@@ -547,7 +561,7 @@ static int add_passwd (struct passwd *pw - if (strcmp (pwd->pw_passwd, "x") != 0) { - return update_passwd (pwd, password); - } --#else /* USE_PAM */ -+#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ - /* - * If there is already a shadow entry, do not touch it. - * If there is already a passwd entry with a password, do not -@@ -558,14 +572,14 @@ static int add_passwd (struct passwd *pw - || (strcmp (pwd->pw_passwd, "x") != 0)) { - return 0; - } --#endif /* USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID && !USE_PAM */ - - /* - * Now the really hard case - I need to create an entirely new - * shadow password file entry. - */ - spent.sp_namp = pwd->pw_name; --#ifndef USE_PAM -+#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { - spent.sp_pwdp = (char *)password; - } else { -@@ -610,35 +624,41 @@ static int add_passwd (struct passwd *pw - static void process_flags (int argc, char **argv) - { - int c; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - int bad_s; - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - static struct option long_options[] = { - {"badname", no_argument, NULL, 'b'}, -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - {"crypt-method", required_argument, NULL, 'c'}, - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - {"help", no_argument, NULL, 'h'}, - {"system", no_argument, NULL, 'r'}, - {"root", required_argument, NULL, 'R'}, -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - {"sha-rounds", required_argument, NULL, 's'}, - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - {NULL, 0, NULL, '\0'} - }; - - while ((c = getopt_long (argc, argv, --#ifndef USE_PAM -+#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - "c:bhrs:", - #else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ - "c:bhr", - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ --#else /* USE_PAM */ -+#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ - "bhr", - #endif - long_options, NULL)) != -1) { -@@ -646,11 +666,13 @@ static void process_flags (int argc, cha - case 'b': - allow_bad_names = true; - break; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - case 'c': - crypt_method = optarg; - break; - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - case 'h': - usage (EXIT_SUCCESS); - break; -@@ -659,6 +681,7 @@ static void process_flags (int argc, cha - break; - case 'R': /* no-op, handled in process_root_flag () */ - break; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': -@@ -698,6 +721,7 @@ static void process_flags (int argc, cha - break; - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - default: - usage (EXIT_FAILURE); - break; -@@ -730,6 +754,7 @@ static void process_flags (int argc, cha - */ - static void check_flags (void) - { -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg && !cflg) { -@@ -762,6 +787,7 @@ static void check_flags (void) - } - } - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - } - - /* -@@ -1052,12 +1078,14 @@ int main (int argc, char **argv) - int line = 0; - uid_t uid; - gid_t gid; -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - int *lines = NULL; - char **usernames = NULL; - char **passwords = NULL; - unsigned int nusers = 0; - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -1195,6 +1223,7 @@ int main (int argc, char **argv) - } - newpw = *pw; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - /* keep the list of user/password for later update by PAM */ - nusers++; -@@ -1211,6 +1240,7 @@ int main (int argc, char **argv) - usernames[nusers-1] = strdup (fields[0]); - passwords[nusers-1] = strdup (fields[1]); - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - if (add_passwd (&newpw, fields[1]) != 0) { - fprintf (stderr, - _("%s: line %d: can't update password\n"), -@@ -1327,6 +1357,7 @@ int main (int argc, char **argv) - nscd_flush_cache ("group"); - sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - unsigned int i; - /* Now update the passwords using PAM */ -@@ -1339,6 +1370,7 @@ int main (int argc, char **argv) - } - } - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - exit (EXIT_SUCCESS); - } diff --git a/shadow-4.15.0-date-parsing.patch b/shadow-4.15.0-date-parsing.patch deleted file mode 100644 index 272d2df..0000000 --- a/shadow-4.15.0-date-parsing.patch +++ /dev/null @@ -1,69 +0,0 @@ -Index: shadow-4.5/lib/getdate.y -=================================================================== ---- shadow-4.5.orig/lib/getdate.y -+++ shadow-4.5/lib/getdate.y -@@ -152,6 +152,7 @@ static int yyHaveDay; - static int yyHaveRel; - static int yyHaveTime; - static int yyHaveZone; -+static int yyHaveYear; - static int yyTimezone; - static int yyDay; - static int yyHour; -@@ -293,18 +294,21 @@ date : tUNUMBER '/' tUNUMBER { - yyDay = $3; - yyYear = $5; - } -+ yyHaveYear++; - } - | tUNUMBER tSNUMBER tSNUMBER { - /* ISO 8601 format. yyyy-mm-dd. */ - yyYear = $1; - yyMonth = -$2; - yyDay = -$3; -+ yyHaveYear++; - } - | tUNUMBER tMONTH tSNUMBER { - /* e.g. 17-JUN-1992. */ - yyDay = $1; - yyMonth = $2; - yyYear = -$3; -+ yyHaveYear++; - } - | tMONTH tUNUMBER { - yyMonth = $1; -@@ -314,6 +318,7 @@ date : tUNUMBER '/' tUNUMBER { - yyMonth = $1; - yyDay = $2; - yyYear = $4; -+ yyHaveYear++; - } - | tUNUMBER tMONTH { - yyMonth = $2; -@@ -323,6 +328,7 @@ date : tUNUMBER '/' tUNUMBER { - yyMonth = $2; - yyDay = $1; - yyYear = $3; -+ yyHaveYear++; - } - ; - -@@ -395,7 +401,8 @@ relunit : tUNUMBER tYEAR_UNIT { - - number : tUNUMBER - { -- if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0)) -+ if ((yyHaveTime != 0 || $1 >= 100) && !yyHaveYear -+ && (yyHaveDate != 0) && (yyHaveRel == 0)) - yyYear = $1; - else - { -@@ -802,7 +809,7 @@ yylex (void) - return LookupWord (buff); - } - if (c != '(') -- return *yyInput++; -+ return (unsigned char)*yyInput++; - Count = 0; - do - { diff --git a/shadow-4.15.0-getdef-spurious-error.patch b/shadow-4.15.0-getdef-spurious-error.patch deleted file mode 100644 index 9cec295..0000000 --- a/shadow-4.15.0-getdef-spurious-error.patch +++ /dev/null @@ -1,137 +0,0 @@ -From ead55e9ba8958504e23e29545f90c4dd925c7462 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Wed, 20 Mar 2024 17:39:46 -0500 -Subject: [PATCH] getdef: avoid spurious error messages about unknown - configuration options - -def_find can return NULL for unset, not just unknown, config options. So -move the decision of whether to log an error message about an unknown config -option back into def_find, which knows the difference. Only putdef_str() -will pass a char* srcfile to def_find, so only calls from putdef_str will -cause the message, which was the original intent of fa68441bc4be8. - -closes #967 - -fixes: fa68441bc4be8 ("Improve the login.defs unknown item error message") -Signed-off-by: Serge Hallyn ---- - lib/getdef.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) - -diff --git a/lib/getdef.c b/lib/getdef.c -index 4d4d4e19..ef2ae1f0 100644 ---- a/lib/getdef.c -+++ b/lib/getdef.c -@@ -176,7 +176,7 @@ static const char* def_fname = LOGINDEFS; /* login config defs file */ - static bool def_loaded = false; /* are defs already loaded? */ - - /* local function prototypes */ --static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *); -+static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *, const char *); - static void def_load (void); - - -@@ -195,7 +195,7 @@ static void def_load (void); - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - return (NULL == d) ? NULL : d->value; - } - -@@ -214,7 +214,7 @@ bool getdef_bool (const char *item) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return false; - } -@@ -240,7 +240,7 @@ int getdef_num (const char *item, int dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -275,7 +275,7 @@ unsigned int getdef_unum (const char *item, unsigned int dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -310,7 +310,7 @@ long getdef_long (const char *item, long dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -342,7 +342,7 @@ unsigned long getdef_ulong (const char *item, unsigned long dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -375,12 +375,9 @@ int putdef_str (const char *name, const char *value, const char *srcfile) - * Locate the slot to save the value. If this parameter - * is unknown then "def_find" will print an err message. - */ -- d = def_find (name); -- if (NULL == d) { -- if (NULL != srcfile) -- SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile)); -+ d = def_find (name, srcfile); -+ if (NULL == d) - return -1; -- } - - /* - * Save off the value. -@@ -404,9 +401,12 @@ int putdef_str (const char *name, const char *value, const char *srcfile) - * - * Search through a table of configurable items to locate the - * specified configuration option. -+ * -+ * If srcfile is not NULL, and the item is not found, then report an error saying -+ * the unknown item was used in this file. - */ - --static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name) -+static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name, const char *srcfile) - { - struct itemdef *ptr; - -@@ -432,6 +432,8 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name) - fprintf (shadow_logfd, - _("configuration error - unknown item '%s' (notify administrator)\n"), - name); -+ if (srcfile != NULL) -+ SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile)); - - out: - return NULL; -@@ -610,7 +612,7 @@ int main (int argc, char **argv) - def_load (); - - for (i = 0; i < NUMDEFS; ++i) { -- d = def_find (def_table[i].name); -+ d = def_find (def_table[i].name, NULL); - if (NULL == d) { - printf ("error - lookup '%s' failed\n", - def_table[i].name); --- -2.44.0 - diff --git a/shadow-4.15.0-manfix.patch b/shadow-4.15.0-manfix.patch deleted file mode 100644 index 34e62f9..0000000 --- a/shadow-4.15.0-manfix.patch +++ /dev/null @@ -1,162 +0,0 @@ -diff -up shadow-4.15.0/man/groupmems.8.xml.manfix shadow-4.15.0/man/groupmems.8.xml ---- shadow-4.15.0/man/groupmems.8.xml.manfix 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.15.0/man/groupmems.8.xml 2024-02-09 10:42:20.337036378 +0100 -@@ -156,20 +156,10 @@ - - SETUP - -- The groupmems executable should be in mode -- 2710 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 2710 groupmems -- $ chown root:groups groupmems -- $ groupmems -g groups -a gk4 -- - - - -diff -up shadow-4.15.0/man/ja/man5/login.defs.5.manfix shadow-4.15.0/man/ja/man5/login.defs.5 ---- shadow-4.15.0/man/ja/man5/login.defs.5.manfix 2023-03-13 21:58:56.000000000 +0100 -+++ shadow-4.15.0/man/ja/man5/login.defs.5 2024-02-09 10:42:20.337036378 +0100 -@@ -123,10 +123,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.15.0/man/login.defs.5.xml.manfix shadow-4.15.0/man/login.defs.5.xml ---- shadow-4.15.0/man/login.defs.5.xml.manfix 2024-01-22 22:36:43.000000000 +0100 -+++ shadow-4.15.0/man/login.defs.5.xml 2024-02-09 10:45:49.014407259 +0100 -@@ -144,6 +144,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: - - -@@ -240,16 +251,6 @@ - - - -- chfn -- -- -- CHFN_AUTH -- CHFN_RESTRICT -- LOGIN_STRING -- -- -- -- - chgpasswd - - -@@ -276,14 +277,6 @@ - - - -- -- chsh -- -- -- CHSH_AUTH LOGIN_STRING -- -- -- - - - -@@ -352,34 +345,6 @@ - LASTLOG_UID_MAX - - -- -- 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 LASTLOG_UID_MAX -- 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 -@@ -451,32 +416,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 --git a/shadow-4.15.1-audit-update.patch b/shadow-4.15.1-audit-update.patch deleted file mode 100644 index a738d60..0000000 --- a/shadow-4.15.1-audit-update.patch +++ /dev/null @@ -1,2062 +0,0 @@ -diff -up shadow-4.15.1/lib/audit_help.c.audit-update shadow-4.15.1/lib/audit_help.c ---- shadow-4.15.1/lib/audit_help.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/audit_help.c 2024-05-20 11:52:05.639758532 +0200 -@@ -48,7 +48,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" -@@ -68,6 +68,39 @@ void audit_logger (int type, MAYBE_UNUSE - } - } - -+/* -+ * 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, MAYBE_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.15.1/lib/cleanup_group.c.audit-update shadow-4.15.1/lib/cleanup_group.c ---- shadow-4.15.1/lib/cleanup_group.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/cleanup_group.c 2024-05-20 11:52:05.639758532 +0200 -@@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cle - gr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, log_get_progname(), -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -80,7 +80,7 @@ void cleanup_report_mod_gshadow (void *c - sgr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, log_get_progname(), -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -101,7 +101,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, log_get_progname(), -- "adding group to /etc/group", -+ "adding-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -120,8 +120,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, log_get_progname(), -- "adding group to /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), -+ "adding-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -143,8 +143,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, log_get_progname(), -- "removing group from /etc/group", -+ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), -+ "removing-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -166,8 +166,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, log_get_progname(), -- "removing group from /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), -+ "removing-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -187,7 +187,7 @@ void cleanup_unlock_group (MAYBE_UNUSED - log_get_progname(), 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 - } -@@ -207,7 +207,7 @@ void cleanup_unlock_gshadow (MAYBE_UNUSE - log_get_progname(), 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.15.1/lib/cleanup_user.c.audit-update shadow-4.15.1/lib/cleanup_user.c ---- shadow-4.15.1/lib/cleanup_user.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/cleanup_user.c 2024-05-20 11:52:05.639758532 +0200 -@@ -44,7 +44,7 @@ void cleanup_report_mod_passwd (void *cl - pw_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, log_get_progname(), -+ audit_logger (AUDIT_USER_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -65,7 +65,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, log_get_progname(), -- "adding user to /etc/passwd", -+ "adding-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -84,8 +84,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, log_get_progname(), -- "adding user to /etc/shadow", -+ audit_logger (AUDIT_USER_MGMT, log_get_progname(), -+ "adding-shadow-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -104,7 +104,7 @@ void cleanup_unlock_passwd (MAYBE_UNUSED - log_get_progname(), 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 - } -@@ -123,7 +123,7 @@ void cleanup_unlock_shadow (MAYBE_UNUSED - log_get_progname(), 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.15.1/lib/prototypes.h.audit-update shadow-4.15.1/lib/prototypes.h ---- shadow-4.15.1/lib/prototypes.h.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/prototypes.h 2024-05-20 11:52:05.639758532 +0200 -@@ -198,12 +198,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, MAYBE_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.15.1/src/chage.c.audit-update shadow-4.15.1/src/chage.c ---- shadow-4.15.1/src/chage.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/chage.c 2024-05-20 11:52:05.639758532 +0200 -@@ -110,8 +110,8 @@ fail_exit (int code) - - #ifdef WITH_AUDIT - if (E_SUCCESS != code) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change age", user_name, user_uid, 0); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-age", user_name, user_uid, SHADOW_AUDIT_FAILURE); - } - #endif - -@@ -846,10 +846,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, user_uid, 1); --#endif -+ /* Displaying fields is not of interest to audit */ - list_fields (); - fail_exit (E_SUCCESS); - } -@@ -868,39 +865,39 @@ int main (int argc, char **argv) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change all aging information", -- user_name, user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-all-aging-information", -+ user_name, user_uid, SHADOW_AUDIT_SUCCESS); - } - #endif - } else { - #ifdef WITH_AUDIT - if (Mflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change max age", user_name, user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-max-age", user_name, user_uid, SHADOW_AUDIT_SUCCESS); - } - if (mflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change min age", user_name, user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-min-age", user_name, 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, 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, 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, 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, user_uid, 1); - } - #endif -diff -up shadow-4.15.1/src/gpasswd.c.audit-update shadow-4.15.1/src/gpasswd.c ---- shadow-4.15.1/src/gpasswd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/gpasswd.c 2024-05-20 11:52:05.640758536 +0200 -@@ -125,7 +125,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 -@@ -384,20 +384,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, "%s failed to add user %s to group %s%s", -- myname, user, group, suffix); -- 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) { -@@ -405,11 +399,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, "%s failed to remove user %s from group %s%s", -- myname, user, group, suffix); -- 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) { -@@ -417,11 +409,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, "%s failed to remove password of group %s%s", -- myname, group, suffix); -- 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) { -@@ -429,11 +419,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, "%s failed to restrict access to group %s%s", -- myname, group, suffix); -- 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) { -@@ -443,11 +431,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, "%s failed to set the administrators of group %s to %s%s", -- myname, group, admins, suffix); -- 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 - } -@@ -457,11 +443,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, "%s failed to set the members of group %s to %s%s", -- myname, group, members, suffix); -- 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 - } -@@ -470,11 +454,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, "%s failed to change password of group %s%s", -- myname, group, suffix); -- 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 - } -@@ -514,11 +496,9 @@ static void log_gpasswd_success (const c - "user %s added by %s to group %s%s", - user, myname, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "user %s added by %s to group %s%s", -- user, myname, group, suffix); -- 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) { -@@ -526,11 +506,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, "user %s removed by %s from group %s%s", -- user, myname, group, suffix); -- 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) { -@@ -540,9 +518,9 @@ static void log_gpasswd_success (const c - #ifdef WITH_AUDIT - SNPRINTF(buf, "password of group %s removed by %s%s", - group, myname, suffix); -- 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) { -@@ -552,9 +530,9 @@ static void log_gpasswd_success (const c - #ifdef WITH_AUDIT - SNPRINTF(buf, "access to group %s restricted by %s%s", - group, myname, suffix); -- 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) { -@@ -564,11 +542,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, "administrators of group %s set by %s to %s%s", -- group, myname, admins, suffix); -- 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 - } -@@ -578,11 +554,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, "members of group %s set by %s to %s%s", -- group, myname, members, suffix); -- 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 - } -@@ -591,11 +565,9 @@ static void log_gpasswd_success (const c - "password of group %s changed by %s%s", - group, myname, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "password of group %s changed by %s%s", -- group, myname, suffix); -- 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.15.1/src/groupadd.c.audit-update shadow-4.15.1/src/groupadd.c ---- shadow-4.15.1/src/groupadd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/groupadd.c 2024-05-20 11:52:05.640758536 +0200 -@@ -115,6 +115,15 @@ usage (int status) - 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 - * -@@ -211,7 +220,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 - /* -@@ -221,7 +230,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 */ - } -@@ -245,7 +254,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); - } - - /* -@@ -261,11 +270,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, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "group added to %s: name=%s, GID=%u", -@@ -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, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "group added to %s: name=%s", -@@ -299,10 +308,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, 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); -@@ -320,7 +325,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); - -@@ -330,7 +335,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); - } -@@ -346,7 +351,7 @@ static void open_files (void) - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s: %s\n"), Prog, gr_dbname (), strerror(errno)); - SYSLOG ((LOG_WARN, "cannot open %s: %s", gr_dbname (), strerror(errno))); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef SHADOWGRP -@@ -356,7 +361,7 @@ static void open_files (void) - _("%s: cannot open %s: %s\n"), - Prog, sgr_dbname (), strerror(errno)); - SYSLOG ((LOG_WARN, "cannot open %s: %s", sgr_dbname (), strerror(errno))); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -493,7 +498,7 @@ static void check_flags (void) - fprintf (stderr, - _("%s: group '%s' already exists\n"), - Prog, group_name); -- exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE); - } - - if (gflg && (prefix_getgrgid (group_id) != NULL)) { -@@ -512,7 +517,7 @@ static void check_flags (void) - fprintf (stderr, - _("%s: GID '%lu' already exists\n"), - Prog, (unsigned long) group_id); -- exit (E_GID_IN_USE); -+ fail_exit (E_GID_IN_USE); - } - } - } -@@ -540,7 +545,7 @@ static void check_perms (void) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); -@@ -560,7 +565,7 @@ static void check_perms (void) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- exit (1); -+ fail_exit (1); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -591,7 +596,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot setup cleanup service.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - /* -@@ -618,7 +623,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.15.1/src/groupdel.c.audit-update shadow-4.15.1/src/groupdel.c ---- shadow-4.15.1/src/groupdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/groupdel.c 2024-05-20 11:52:05.640758536 +0200 -@@ -87,6 +87,15 @@ usage (int status) - 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 - * -@@ -113,7 +122,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 -@@ -125,7 +134,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 */ -@@ -144,12 +153,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, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -168,12 +177,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, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -186,11 +195,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, group_id, SHADOW_AUDIT_SUCCESS); --#endif - SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); - del_cleanup (cleanup_report_del_group); - } -@@ -207,7 +211,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 -@@ -216,7 +220,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); - } -@@ -234,7 +238,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) { -@@ -243,7 +247,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 */ -@@ -284,7 +288,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); - } - - /* -@@ -368,7 +372,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); -@@ -382,7 +386,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 (Prog, pampw->pw_name, &conv, &pamh); -@@ -403,7 +407,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 */ -@@ -423,7 +427,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; -@@ -447,7 +451,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.15.1/src/groupmod.c.audit-update shadow-4.15.1/src/groupmod.c ---- shadow-4.15.1/src/groupmod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/groupmod.c 2024-05-20 11:52:05.640758536 +0200 -@@ -474,7 +474,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); -@@ -497,7 +497,14 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ /* If both happened, log password change as its more important */ -+ if (pflg) -+ audit_logger (AUDIT_GRP_CHAUTHTOK, Prog, -+ info_gshadow.audit_msg, -+ group_name, AUDIT_NO_ID, -+ SHADOW_AUDIT_SUCCESS); -+ else -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_gshadow.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -520,7 +527,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); -@@ -535,8 +542,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 -diff -up shadow-4.15.1/src/newgrp.c.audit-update shadow-4.15.1/src/newgrp.c ---- shadow-4.15.1/src/newgrp.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/newgrp.c 2024-05-20 11:52:05.640758536 +0200 -@@ -188,10 +188,10 @@ static void check_perms (const struct gr - if (grp->gr_passwd[0] == '\0' || - strcmp (cpasswd, grp->gr_passwd) != 0) { - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "authentication new-gid=%lu", -+ SNPRINTF(audit_buf, "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); - audit_logger (AUDIT_GRP_AUTH, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - SYSLOG ((LOG_INFO, - "Invalid password for group '%s' from '%s'", -@@ -201,10 +201,10 @@ static void check_perms (const struct gr - goto failure; - } - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "authentication new-gid=%lu", -+ SNPRINTF(audit_buf, "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); - audit_logger (AUDIT_GRP_AUTH, Prog, -- audit_buf, NULL, getuid (), 1); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); - #endif - } - -@@ -215,16 +215,6 @@ failure: - * harm. -- JWP - */ - closelog (); --#ifdef WITH_AUDIT -- if (groupname) { -- SNPRINTF(audit_buf, "changing new-group=%s", groupname); -- audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -- } else { -- audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -- } --#endif - exit (EXIT_FAILURE); - } - -@@ -298,13 +288,23 @@ static void syslog_sg (const char *name, - is_newgrp ? "newgrp" : "sg", strerror (errno)); - #ifdef WITH_AUDIT - if (group) { -- SNPRINTF(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, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -@@ -440,7 +440,7 @@ int main (int argc, char **argv) - Prog); - #ifdef WITH_AUDIT - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", - (unsigned long) getuid ())); -@@ -556,12 +556,22 @@ int main (int argc, char **argv) - perror ("getgroups"); - #ifdef WITH_AUDIT - if (group) { -- SNPRINTF(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, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -@@ -715,9 +725,9 @@ int main (int argc, char **argv) - if (setgid (gid) != 0) { - perror ("setgid"); - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - exit (EXIT_FAILURE); - } -@@ -725,9 +735,9 @@ int main (int argc, char **argv) - if (setuid (getuid ()) != 0) { - perror ("setuid"); - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - exit (EXIT_FAILURE); - } -@@ -740,9 +750,9 @@ int main (int argc, char **argv) - closelog (); - execl (SHELL, "sh", "-c", command, (char *) NULL); - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - perror (SHELL); - exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); -@@ -806,9 +816,9 @@ int main (int argc, char **argv) - } - - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 1); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); - #endif - /* - * Exec the login shell and go away. We are trying to get back to -@@ -832,12 +842,22 @@ int main (int argc, char **argv) - closelog (); - #ifdef WITH_AUDIT - if (NULL != group) { -- SNPRINTF(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, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -diff -up shadow-4.15.1/src/useradd.c.audit-update shadow-4.15.1/src/useradd.c ---- shadow-4.15.1/src/useradd.c.audit-update 2024-05-20 11:52:05.635758519 +0200 -+++ shadow-4.15.1/src/useradd.c 2024-05-20 11:52:05.640758536 +0200 -@@ -245,6 +245,8 @@ static FILE *fmkstemp(char *template); - */ - static void fail_exit (int code) - { -+ int type; -+ - if (home_added && rmdir(prefix_user_home) != 0) { - fprintf(stderr, - _("%s: %s was created, but could not be removed\n"), -@@ -255,38 +257,22 @@ static void fail_exit (int code) - if (spw_locked && 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 */ - } - if (pw_locked && 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 */ - } - if (gr_locked && 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 */ - } - #ifdef SHADOWGRP - if (sgr_locked && sgr_unlock() == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); --# ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "unlocking gshadow file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --# endif - /* continue */ - } - #endif -@@ -294,27 +280,23 @@ static void fail_exit (int code) - if (sub_uid_locked && 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 */ - } - if (sub_gid_locked && 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 - SYSLOG((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); -@@ -727,7 +709,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 -@@ -1056,12 +1038,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 */ - } - -@@ -1075,18 +1051,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, -@@ -1131,12 +1101,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 */ - } - -@@ -1150,18 +1114,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, -@@ -1556,7 +1515,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 -@@ -1656,7 +1615,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 -@@ -1669,7 +1628,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 -@@ -1686,7 +1645,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 -@@ -1700,7 +1659,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 -@@ -1963,7 +1922,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 -@@ -1979,7 +1938,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 -@@ -1989,7 +1948,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 -@@ -2191,11 +2150,6 @@ static void usr_update (unsigned long su - 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, user_id, SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_PW_UPDATE); - } - #ifdef ENABLE_SUBIDS -@@ -2222,7 +2176,7 @@ static void usr_update (unsigned long su - * and we can use the real ID thereafter. - */ - audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -+ "add-user", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -2317,10 +2271,6 @@ static void create_home (void) - if (mkdir(path, 0) != 0) { - fprintf(stderr, _("%s: cannot create directory %s\n"), - Prog, path); --#ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "adding home directory", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif - fail_exit(E_HOMEDIR); - } - if (chown(path, 0, 0) < 0) { -@@ -2345,7 +2295,7 @@ static void create_home (void) - } - 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, user_id, SHADOW_AUDIT_SUCCESS); - #endif - #ifdef WITH_SELINUX -@@ -2586,12 +2536,6 @@ int main (int argc, char **argv) - */ - if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ - fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_NAME_IN_USE); - } - -@@ -2607,12 +2551,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); - } - } -@@ -2642,12 +2580,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, user_id, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_UID_IN_USE); - } - } -@@ -2722,9 +2654,9 @@ 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, user_id, 0); -+ audit_logger (AUDIT_ROLE_ASSIGN, Prog, -+ "add-selinux-user-mapping", -+ user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - fail_exit (E_SE_UPDATE); - } -diff -up shadow-4.15.1/src/userdel.c.audit-update shadow-4.15.1/src/userdel.c ---- shadow-4.15.1/src/userdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/userdel.c 2024-05-20 11:52:05.641758539 +0200 -@@ -206,9 +206,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, user_id, SHADOW_AUDIT_SUCCESS); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "deleting-user-from-group", -+ user_name, user_id, ngrp->gr_name, SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", - user_name, ngrp->gr_name)); -@@ -267,9 +267,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, user_id, SHADOW_AUDIT_SUCCESS); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "deleting-user-from-shadow-group", -+ user_name, user_id, nsgrp->sg_name, SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", - user_name, nsgrp->sg_name)); -@@ -345,9 +345,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, -@@ -363,9 +363,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, -@@ -527,7 +527,7 @@ static void fail_exit (int code) - - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user", -+ "delete-user", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - -@@ -546,22 +546,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening password file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - if (is_shadow_pwd) { -@@ -569,11 +559,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - spw_locked = true; -@@ -581,11 +566,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - } -@@ -593,21 +573,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP -@@ -616,22 +586,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - sgr_locked= true; - if (sgr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening shadow group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - } -@@ -642,22 +602,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_UID_UPDATE); - } - sub_uid_locked = true; - if (sub_uid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening subordinate user file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_UID_UPDATE); - } - } -@@ -666,22 +616,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, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_GID_UPDATE); - } - sub_gid_locked = true; - if (sub_gid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening subordinate group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_GID_UPDATE); - } - } -@@ -726,7 +666,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, user_id, SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name)); -@@ -824,7 +764,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, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - free(mailfile); -@@ -840,7 +780,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, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - errors = 1; -@@ -849,8 +789,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, user_id, SHADOW_AUDIT_SUCCESS); - } - #endif /* WITH_AUDIT */ -@@ -867,7 +807,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, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - free(mailfile); -@@ -883,7 +823,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, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - errors = 1; -@@ -892,8 +832,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, user_id, SHADOW_AUDIT_SUCCESS); - } - #endif /* WITH_AUDIT */ -@@ -1104,7 +1044,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 */ -@@ -1154,7 +1094,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 */ -@@ -1248,8 +1188,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, user_id, SHADOW_AUDIT_SUCCESS); - } - #endif /* WITH_AUDIT */ -@@ -1257,7 +1197,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); - } -@@ -1270,8 +1210,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, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - fail_exit (E_SE_UPDATE); -diff -up shadow-4.15.1/src/usermod.c.audit-update shadow-4.15.1/src/usermod.c ---- shadow-4.15.1/src/usermod.c.audit-update 2024-05-20 11:52:05.638758529 +0200 -+++ shadow-4.15.1/src/usermod.c 2024-05-20 11:56:51.962509443 +0200 -@@ -440,7 +440,7 @@ static char *new_pw_passwd (char *pw_pas - - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating passwd", user_newname, user_newid, 0); -+ "updating-passwd", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); - strcpy (buf, "!"); -@@ -457,14 +457,14 @@ static char *new_pw_passwd (char *pw_pas - - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating password", user_newname, user_newid, 0); -+ "updating-password", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); - memmove(pw_pass, pw_pass + 1, strlen(pw_pass)); - } else if (pflg) { - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing password", user_newname, user_newid, 1); -+ "updating-password", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); - pw_pass = xstrdup (user_pass); -@@ -492,8 +492,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", user_newname, user_newid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-name", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, - "change user name '%s' to '%s'", -@@ -512,8 +512,8 @@ static void new_pwent (struct passwd *pw - - if (uflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing uid", user_newname, user_newid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-uid", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, - "change user '%s' UID from '%d' to '%d'", -@@ -522,8 +522,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, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -533,16 +533,16 @@ static void new_pwent (struct passwd *pw - } - if (cflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing comment", user_newname, user_newid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-comment", user_newname, user_newid, 1); - #endif - pwent->pw_gecos = user_newcomment; - } - - 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, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -558,8 +558,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, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -589,8 +589,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, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -604,8 +604,8 @@ static void new_spent (struct spwd *spen - date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); - date_to_str (sizeof(old_exp), 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, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -690,9 +690,9 @@ fail_exit (int code) - #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); - } -@@ -762,9 +762,12 @@ update_group(const struct group *grp) - 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'", -@@ -778,9 +781,11 @@ update_group(const struct group *grp) - 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'", -@@ -793,9 +798,11 @@ update_group(const struct group *grp) - 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)); -@@ -888,9 +895,10 @@ update_gshadow(const struct sgrp *sgrp) - 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'", -@@ -910,9 +918,10 @@ update_gshadow(const struct sgrp *sgrp) - 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'", -@@ -926,9 +935,10 @@ update_gshadow(const struct sgrp *sgrp) - 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'", -@@ -941,9 +951,10 @@ update_gshadow(const struct sgrp *sgrp) - 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)); -@@ -1852,8 +1863,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, user_newid, 1); - } - #endif -@@ -1871,8 +1882,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, user_newid, 1); - #endif - return; -@@ -1899,9 +1910,9 @@ static void move_home (void) - Prog, prefix_user_home); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, -+ audit_logger (AUDIT_USER_MGMT, - Prog, -- "moving home directory", -+ "moving-home-dir", - user_newname, - user_newid, - 1); -@@ -2125,8 +2136,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, user_newid, 1); - } - #endif -@@ -2149,8 +2160,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, user_newid, 1); - } - -@@ -2347,8 +2358,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, user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -2360,8 +2371,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, user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -2404,8 +2415,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, user_newid, 1); - } - #endif diff --git a/shadow-4.15.1-sast-fixes.patch b/shadow-4.15.1-sast-fixes.patch deleted file mode 100644 index e674ebf..0000000 --- a/shadow-4.15.1-sast-fixes.patch +++ /dev/null @@ -1,1413 +0,0 @@ -From 4c16416ebc5f0958d58a1ea1e7890eafd9f8bb75 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Wed, 15 May 2024 12:25:51 +0200 -Subject: [PATCH 01/16] port: fix OVERRUN (CWE-119) - -``` -shadow-4.15.0/lib/port.c:154:2: alias: Assigning: "port.pt_names" = "ttys". "port.pt_names" now points to element 0 of "ttys" (which consists of 65 8-byte elements). -shadow-4.15.0/lib/port.c:155:2: cond_const: Checking "j < 64" implies that "j" is 64 on the false branch. -shadow-4.15.0/lib/port.c:175:2: overrun-local: Overrunning array of 65 8-byte elements at element index 65 (byte offset 527) by dereferencing pointer "port.pt_names + (j + 1)". -173| *cp = '\0'; -174| cp++; -175|-> port.pt_names[j + 1] = NULL; -176| -177| /* -``` - -Resolves: https://issues.redhat.com/browse/RHEL-35383 - -Signed-off-by: Iker Pedrosa -Reviewed-by: Alejandro Colomar ---- - lib/port.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/port.c b/lib/port.c -index 05b95651..60ff8989 100644 ---- a/lib/port.c -+++ b/lib/port.c -@@ -168,7 +168,7 @@ again: - } - *cp = '\0'; - cp++; -- port.pt_names[j + 1] = NULL; -+ port.pt_names[j] = NULL; - - /* - * Get the list of user names. It is the second colon --- -2.45.1 - - -From f8fc6371f69930bbd5801284256e182ba35ced2a Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 14:05:31 +0200 -Subject: [PATCH 02/16] src/useradd.c: set_defaults(): Fix order of clean-ups - -Resources should be freed in the inverse order of the allocation. -This refactor prepares for the following commits, which fix some leaks. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 88d8ab7f..56a74559 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -745,10 +745,9 @@ static int set_defaults (void) - def_create_mail_spool, def_log_init)); - ret = 0; - setdef_err: -- free(new_file); -- if (prefix[0]) { -+ if (prefix[0]) - free(default_file); -- } -+ free(new_file); - - return ret; - } --- -2.45.1 - - -From 37ae8827a0869ee4a723954c3c9e7c48165d9b50 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 14:28:50 +0200 -Subject: [PATCH 03/16] src/useradd.c: set_defaults(): Rename goto label - -This will help add other labels in the following commits. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 24 +++++++++++++----------- - 1 file changed, 13 insertions(+), 11 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 56a74559..bc72e6bc 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -558,7 +558,7 @@ static int set_defaults (void) - fprintf(stderr, - _("%s: cannot create new defaults file: %s\n"), - Prog, strerror(errno)); -- goto setdef_err; -+ goto err_free_def; - } - } - -@@ -567,7 +567,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: cannot create directory for defaults file\n"), - Prog); -- goto setdef_err; -+ goto err_free_def; - } - - ret = mkdir(dirname(new_file_dup), 0755); -@@ -576,7 +576,7 @@ static int set_defaults (void) - _("%s: cannot create directory for defaults file\n"), - Prog); - free(new_file_dup); -- goto setdef_err; -+ goto err_free_def; - } - free(new_file_dup); - -@@ -588,7 +588,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: cannot create new defaults file\n"), - Prog); -- goto setdef_err; -+ goto err_free_def; - } - - ofp = fdopen (ofd, "w"); -@@ -596,7 +596,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: cannot open new defaults file\n"), - Prog); -- goto setdef_err; -+ goto err_free_def; - } - - /* -@@ -623,7 +623,7 @@ static int set_defaults (void) - _("%s: line too long in %s: %s..."), - Prog, default_file, buf); - (void) fclose (ifp); -- goto setdef_err; -+ goto err_free_def; - } - } - -@@ -702,9 +702,10 @@ static int set_defaults (void) - (void) fflush (ofp); - if ( (ferror (ofp) != 0) - || (fsync (fileno (ofp)) != 0) -- || (fclose (ofp) != 0)) { -+ || (fclose (ofp) != 0)) -+ { - unlink (new_file); -- goto setdef_err; -+ goto err_free_def; - } - - /* -@@ -718,7 +719,7 @@ static int set_defaults (void) - _("%s: Cannot create backup file (%s): %s\n"), - Prog, buf, strerror (err)); - unlink (new_file); -- goto setdef_err; -+ goto err_free_def; - } - - /* -@@ -729,7 +730,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: rename: %s: %s\n"), - Prog, new_file, strerror (err)); -- goto setdef_err; -+ goto err_free_def; - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USYS_CONFIG, Prog, -@@ -744,7 +745,8 @@ static int set_defaults (void) - def_inactive, def_expire, def_template, - def_create_mail_spool, def_log_init)); - ret = 0; -- setdef_err: -+ -+err_free_def: - if (prefix[0]) - free(default_file); - free(new_file); --- -2.45.1 - - -From 701fe4cf1aeac9e66fa949369c91d135dbf375d2 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:10:46 +0200 -Subject: [PATCH 04/16] src/useradd.c: set_defaults(): Do not free(3) the - result of asprintf(3) if it failed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -See asprintf(3): - -RETURN VALUE - When successful, these functions return the number of bytes - printed, just like sprintf(3). If memory allocation wasn’t possi‐ - ble, or some other error occurs, these functions will return -1, - and the contents of strp are undefined. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index bc72e6bc..6a3edfe3 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -558,7 +558,7 @@ static int set_defaults (void) - fprintf(stderr, - _("%s: cannot create new defaults file: %s\n"), - Prog, strerror(errno)); -- goto err_free_def; -+ goto err_free_new; - } - } - -@@ -749,6 +749,7 @@ static int set_defaults (void) - err_free_def: - if (prefix[0]) - free(default_file); -+err_free_new: - free(new_file); - - return ret; --- -2.45.1 - - -From a74c4b6ae124a55cd272e574e0d056102f331e17 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:14:31 +0200 -Subject: [PATCH 05/16] src/useradd.c: De-duplicate code - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 6a3edfe3..ad2676c1 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -571,14 +571,13 @@ static int set_defaults (void) - } - - ret = mkdir(dirname(new_file_dup), 0755); -+ free(new_file_dup); - if (-1 == ret && EEXIST != errno) { - fprintf (stderr, - _("%s: cannot create directory for defaults file\n"), - Prog); -- free(new_file_dup); - goto err_free_def; - } -- free(new_file_dup); - - /* - * Create a temporary file to copy the new output to. --- -2.45.1 - - -From e7d1508e076bbf4053faacc0370c6fe43d9c8f04 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:40:58 +0200 -Subject: [PATCH 06/16] src/useradd.c: Add fmkstemp() to fix file-descriptor - leak - -This function creates a temporary file, and returns a FILE pointer to -it. This avoids dealing with both a file descriptor and a FILE pointer, -and correctly deallocating the resources on error. - -The code before this patch was leaking the file descriptor if fdopen(3) -failed. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 34 ++++++++++++++++++++++++---------- - 1 file changed, 24 insertions(+), 10 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index ad2676c1..e0238457 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -238,6 +238,9 @@ static void create_home (void); - static void create_mail (void); - static void check_uid_range(int rflg, uid_t user_id); - -+static FILE *fmkstemp(char *template); -+ -+ - /* - * fail_exit - undo as much as possible - */ -@@ -524,7 +527,6 @@ static void show_defaults (void) - */ - static int set_defaults (void) - { -- int ofd; - int ret = -1; - bool out_group = false; - bool out_groups = false; -@@ -582,15 +584,7 @@ static int set_defaults (void) - /* - * Create a temporary file to copy the new output to. - */ -- ofd = mkstemp (new_file); -- if (-1 == ofd) { -- fprintf (stderr, -- _("%s: cannot create new defaults file\n"), -- Prog); -- goto err_free_def; -- } -- -- ofp = fdopen (ofd, "w"); -+ ofp = fmkstemp(new_file); - if (NULL == ofp) { - fprintf (stderr, - _("%s: cannot open new defaults file\n"), -@@ -2752,3 +2746,23 @@ int main (int argc, char **argv) - return E_SUCCESS; - } - -+ -+static FILE * -+fmkstemp(char *template) -+{ -+ int fd; -+ FILE *fp; -+ -+ fd = mkstemp(template); -+ if (fd == -1) -+ return NULL; -+ -+ fp = fdopen(fd, "w"); -+ if (fp == NULL) { -+ close(fd); -+ unlink(template); -+ return NULL; -+ } -+ -+ return fp; -+} --- -2.45.1 - - -From 1ee066ae1e5b39ac42120ad0f6f8af0f102db952 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:52:07 +0200 -Subject: [PATCH 07/16] src/useradd.c: set_defaults(): Fix FILE* leak - -Report: -> shadow-4.15.0/src/useradd.c:575:2: alloc_fn: Storage is returned from allocation function "fdopen". -> shadow-4.15.0/src/useradd.c:575:2: var_assign: Assigning: "ofp" = storage returned from "fdopen(ofd, "w")". -> shadow-4.15.0/src/useradd.c:734:2: leaked_storage: Variable "ofp" going out of scope leaks the storage it points to. -> 732| } -> 733| -> 734|-> return ret; -> 735| } -> 736| - -Link: -Reported-by: Iker Pedrosa -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index e0238457..347334a6 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -615,7 +615,8 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: line too long in %s: %s..."), - Prog, default_file, buf); -- (void) fclose (ifp); -+ fclose(ifp); -+ fclose(ofp); - goto err_free_def; - } - } --- -2.45.1 - - -From 151f14ad69de8100d25c1974947d53ae40d1448a Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 13:52:15 +0200 -Subject: [PATCH 08/16] src/usermod.c: Reduce scope of local variables - -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 0fcf0325..57b58f5b 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -687,11 +687,8 @@ fail_exit (int code) - - static void update_group (void) - { -- bool is_member; -- bool was_member; -- bool changed; -- const struct group *grp; -- struct group *ngrp; -+ bool changed; -+ const struct group *grp; - - changed = false; - -@@ -700,6 +697,9 @@ static void update_group (void) - * the user is a member of. - */ - while ((grp = gr_next ()) != NULL) { -+ bool is_member; -+ bool was_member; -+ struct group *ngrp; - /* - * See if the user specified this group as one of their - * concurrent groups. -@@ -799,12 +799,8 @@ static void update_group (void) - #ifdef SHADOWGRP - static void update_gshadow (void) - { -- bool is_member; -- bool was_member; -- bool was_admin; -- bool changed; -- const struct sgrp *sgrp; -- struct sgrp *nsgrp; -+ bool changed; -+ const struct sgrp *sgrp; - - changed = false; - -@@ -813,6 +809,10 @@ static void update_gshadow (void) - * that the user is a member of. - */ - while ((sgrp = sgr_next ()) != NULL) { -+ bool is_member; -+ bool was_member; -+ bool was_admin; -+ struct sgrp *nsgrp; - - /* - * See if the user was a member of this group --- -2.45.1 - - -From b089a63ab38f69c32d099320fe8181802f7f4092 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 13:49:34 +0200 -Subject: [PATCH 09/16] src/usermod.c: Rename update_group() => - update_group_file() - -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 57b58f5b..aaa83d7d 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -178,7 +178,7 @@ NORETURN static void usage (int status); - static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); - NORETURN static void fail_exit (int); --static void update_group (void); -+static void update_group_file(void); - - #ifdef SHADOWGRP - static void update_gshadow (void); -@@ -685,7 +685,8 @@ fail_exit (int code) - } - - --static void update_group (void) -+static void -+update_group_file(void) - { - bool changed; - const struct group *grp; -@@ -950,7 +951,7 @@ static void update_gshadow (void) - */ - static void grp_update (void) - { -- update_group (); -+ update_group_file(); - #ifdef SHADOWGRP - if (is_shadow_grp) { - update_gshadow (); --- -2.45.1 - - -From 81bc78ec5cdd59790bc7c591c9d1f66bd4d7b78e Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:11:22 +0200 -Subject: [PATCH 10/16] src/usermod.c: Rename update_gshadow() => - update_gshadow_file() - -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index aaa83d7d..3048f801 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -181,7 +181,7 @@ NORETURN static void fail_exit (int); - static void update_group_file(void); - - #ifdef SHADOWGRP --static void update_gshadow (void); -+static void update_gshadow_file(void); - #endif - static void grp_update (void); - -@@ -798,7 +798,8 @@ update_group_file(void) - } - - #ifdef SHADOWGRP --static void update_gshadow (void) -+static void -+update_gshadow_file(void) - { - bool changed; - const struct sgrp *sgrp; -@@ -954,7 +955,7 @@ static void grp_update (void) - update_group_file(); - #ifdef SHADOWGRP - if (is_shadow_grp) { -- update_gshadow (); -+ update_gshadow_file(); - } - #endif - } --- -2.45.1 - - -From 61964aa06b9e6e0643a6519f64290f18ac04867f Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 13:54:06 +0200 -Subject: [PATCH 11/16] src/usermod.c: update_group_file(): Fix RESOURCE_LEAK - (CWE-772) - -Report: -> shadow-4.15.0/src/usermod.c:734:3: alloc_fn: Storage is returned from allocation function "__gr_dup". -> shadow-4.15.0/src/usermod.c:734:3: var_assign: Assigning: "ngrp" = storage returned from "__gr_dup(grp)". -> shadow-4.15.0/src/usermod.c:815:1: leaked_storage: Variable "ngrp" going out of scope leaks the storage it points to. -> 813| gr_free(ngrp); -> 814| } -> 815|-> } -> 816| -> 817| #ifdef SHADOWGRP - -Link: https://issues.redhat.com/browse/RHEL-35383 -Reported-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 3048f801..e0cfdd83 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -780,9 +780,8 @@ update_group_file(void) - SYSLOG ((LOG_INFO, "add '%s' to group '%s'", - user_newname, ngrp->gr_name)); - } -- if (!changed) { -- continue; -- } -+ if (!changed) -+ goto free_ngrp; - - changed = false; - if (gr_update (ngrp) == 0) { -@@ -793,6 +792,7 @@ update_group_file(void) - fail_exit (E_GRP_UPDATE); - } - -+free_ngrp: - gr_free(ngrp); - } - } --- -2.45.1 - - -From 71a3238b7996285fc3c8dec841244ba95d663fa5 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:15:15 +0200 -Subject: [PATCH 12/16] src/usermod.c: update_gshadow_file(): Fix RESOURCE_LEAK - (CWE-772) - -Report: -> shadow-4.15.0/src/usermod.c:864:3: alloc_fn: Storage is returned from allocation function "__sgr_dup". -> shadow-4.15.0/src/usermod.c:864:3: var_assign: Assigning: "nsgrp" = storage returned from "__sgr_dup(sgrp)". -> shadow-4.15.0/src/usermod.c:964:1: leaked_storage: Variable "nsgrp" going out of scope leaks the storage it points to. -> 962| free (nsgrp); -> 963| } -> 964|-> } -> 965| #endif /* SHADOWGRP */ -> 966| - -Link: https://issues.redhat.com/browse/RHEL-35383 -Reported-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index e0cfdd83..bb5d3535 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -921,9 +921,8 @@ update_gshadow_file(void) - SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", - user_newname, nsgrp->sg_name)); - } -- if (!changed) { -- continue; -- } -+ if (!changed) -+ goto free_nsgrp; - - changed = false; - -@@ -939,6 +938,7 @@ update_gshadow_file(void) - fail_exit (E_GRP_UPDATE); - } - -+free_nsgrp: - free (nsgrp); - } - } --- -2.45.1 - - -From 68d42a8fbe42b89cf13d3f672ad8502dbaf05835 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 14:02:54 +0200 -Subject: [PATCH 13/16] src/usermod.c: update_group_file(): Reduce scope of - local variable - -After _every_ iteration, 'changed' is always 'false'. We don't need to -have it outside of the loop. - -See: - -$ grepc update_group_file . \ -| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - bool changed; - changed = false; - while ((grp = gr_next ()) != NULL) { - if (!was_member && !is_member) { - continue; - } - if (was_member) { - if ((!Gflg) || is_member) { - if (lflg) { - changed = true; - } - } else { - changed = true; - } - } else if (is_member) { - changed = true; - } - if (!changed) - goto free_ngrp; - changed = false; -free_ngrp: - } -} - -This was already true in the commit that introduced the code: - -$ git show 45c6603cc:src/usermod.c \ -| grepc update_group \ -| grep -e changed -e goto -e break -e continue -e '\' -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - int changed; - changed = 0; - while ((grp = gr_next())) { - * See if the user specified this group as one of their - if (!was_member && !is_member) - continue; - if (was_member && (!Gflg || is_member)) { - if (lflg) { - changed = 1; - } - } else if (was_member && Gflg && !is_member) { - changed = 1; - } else if (!was_member && Gflg && is_member) { - changed = 1; - } - if (!changed) - continue; - changed = 0; - } -} - -Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index bb5d3535..30f47b8a 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -688,19 +688,20 @@ fail_exit (int code) - static void - update_group_file(void) - { -- bool changed; - const struct group *grp; - -- changed = false; -- - /* - * Scan through the entire group file looking for the groups that - * the user is a member of. - */ - while ((grp = gr_next ()) != NULL) { -+ bool changed; - bool is_member; - bool was_member; - struct group *ngrp; -+ -+ changed = false; -+ - /* - * See if the user specified this group as one of their - * concurrent groups. -@@ -783,7 +784,6 @@ update_group_file(void) - if (!changed) - goto free_ngrp; - -- changed = false; - if (gr_update (ngrp) == 0) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), --- -2.45.1 - - -From da77a82ecbc90e89808f143e7fa2abb7650f50d7 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:19:46 +0200 -Subject: [PATCH 14/16] src/usermod.c: update_gshadow_file(): Reduce scope of - local variable - -After _every_ iteration, 'changed' is always 'false'. We don't need to -have it outside of the loop. - -See: - -$ grepc update_gshadow_file . \ -| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - bool changed; - changed = false; - while ((sgrp = sgr_next ()) != NULL) { - if (!was_member && !was_admin && !is_member) { - continue; - } - if (was_admin && lflg) { - changed = true; - } - if (was_member) { - if ((!Gflg) || is_member) { - if (lflg) { - changed = true; - } - } else { - changed = true; - } - } else if (is_member) { - changed = true; - } - if (!changed) - goto free_nsgrp; - changed = false; - } -} - -This was already true in the commit that introduced the code: - -$ git show 45c6603cc:src/usermod.c \ -| grepc update_gshadow \ -| grep -e changed -e goto -e break -e continue -e '\' -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - int changed; - changed = 0; - while ((sgrp = sgr_next())) { - * See if the user was a member of this group - * See if the user was an administrator of this group - * See if the user specified this group as one of their - if (!was_member && !was_admin && !is_member) - continue; - if (was_admin && lflg) { - changed = 1; - } - if (was_member && (!Gflg || is_member)) { - if (lflg) { - changed = 1; - } - } else if (was_member && Gflg && !is_member) { - changed = 1; - } else if (!was_member && Gflg && is_member) { - changed = 1; - } - if (!changed) - continue; - changed = 0; - } -} - -Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 30f47b8a..7b1e0581 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -801,21 +801,21 @@ free_ngrp: - static void - update_gshadow_file(void) - { -- bool changed; - const struct sgrp *sgrp; - -- changed = false; -- - /* - * Scan through the entire shadow group file looking for the groups - * that the user is a member of. - */ - while ((sgrp = sgr_next ()) != NULL) { -+ bool changed; - bool is_member; - bool was_member; - bool was_admin; - struct sgrp *nsgrp; - -+ changed = false; -+ - /* - * See if the user was a member of this group - */ -@@ -924,8 +924,6 @@ update_gshadow_file(void) - if (!changed) - goto free_nsgrp; - -- changed = false; -- - /* - * Update the group entry to reflect the changes. - */ --- -2.45.1 - - -From adf37cccd0fa4ce7d05644514b0af57fe71905c3 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 14:12:09 +0200 -Subject: [PATCH 15/16] src/usermod.c: update_group(): Add helper function - -Keep the while loop in the outer function, and move the iteration code -to this new helper. This makes it a bit more readable. - -Cc: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 167 ++++++++++++++++++++++++++------------------------ - 1 file changed, 87 insertions(+), 80 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 7b1e0581..4ea11376 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -179,6 +179,7 @@ static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); - NORETURN static void fail_exit (int); - static void update_group_file(void); -+static void update_group(const struct group *grp); - - #ifdef SHADOWGRP - static void update_gshadow_file(void); -@@ -694,109 +695,115 @@ update_group_file(void) - * Scan through the entire group file looking for the groups that - * the user is a member of. - */ -- while ((grp = gr_next ()) != NULL) { -- bool changed; -- bool is_member; -- bool was_member; -- struct group *ngrp; -+ while ((grp = gr_next()) != NULL) -+ update_group(grp); -+} - -- changed = false; - -- /* -- * See if the user specified this group as one of their -- * concurrent groups. -- */ -- was_member = is_on_list (grp->gr_mem, user_name); -- is_member = Gflg && ( (was_member && aflg) -- || is_on_list (user_groups, grp->gr_name)); -+static void -+update_group(const struct group *grp) -+{ -+ bool changed; -+ bool is_member; -+ bool was_member; -+ struct group *ngrp; - -- if (!was_member && !is_member) { -- continue; -- } -+ changed = false; - -- /* -- * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes -- * mentioned groups while leaving the others. -- */ -- if (Gflg && rflg) { -- is_member = !is_member; -- } -+ /* -+ * See if the user specified this group as one of their -+ * concurrent groups. -+ */ -+ was_member = is_on_list (grp->gr_mem, user_name); -+ is_member = Gflg && ( (was_member && aflg) -+ || is_on_list (user_groups, grp->gr_name)); - -- ngrp = __gr_dup (grp); -- if (NULL == ngrp) { -- fprintf (stderr, -- _("%s: Out of memory. Cannot update %s.\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -+ if (!was_member && !is_member) -+ return; - -- if (was_member) { -- if ((!Gflg) || is_member) { -- /* User was a member and is still a member -- * of this group. -- * But the user might have been renamed. -- */ -- if (lflg) { -- ngrp->gr_mem = del_list (ngrp->gr_mem, -- user_name); -- ngrp->gr_mem = add_list (ngrp->gr_mem, -- user_newname); -- changed = true; --#ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing group member", -- user_newname, AUDIT_NO_ID, 1); --#endif -- SYSLOG ((LOG_INFO, -- "change '%s' to '%s' in group '%s'", -- user_name, user_newname, -- ngrp->gr_name)); -- } -- } else { -- /* User was a member but is no more a -- * member of this group. -- */ -- ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); -+ /* -+ * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes -+ * mentioned groups while leaving the others. -+ */ -+ if (Gflg && rflg) { -+ is_member = !is_member; -+ } -+ -+ ngrp = __gr_dup (grp); -+ if (NULL == ngrp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot update %s.\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+ if (was_member) { -+ if ((!Gflg) || is_member) { -+ /* User was a member and is still a member -+ * of this group. -+ * But the user might have been renamed. -+ */ -+ if (lflg) { -+ ngrp->gr_mem = del_list (ngrp->gr_mem, -+ user_name); -+ ngrp->gr_mem = add_list (ngrp->gr_mem, -+ user_newname); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing group member", -- user_name, AUDIT_NO_ID, 1); -+ "changing group member", -+ user_newname, AUDIT_NO_ID, 1); - #endif - SYSLOG ((LOG_INFO, -- "delete '%s' from group '%s'", -- user_name, ngrp->gr_name)); -+ "change '%s' to '%s' in group '%s'", -+ user_name, user_newname, -+ ngrp->gr_name)); - } -- } else if (is_member) { -- /* User was not a member but is now a member this -- * group. -+ } else { -+ /* User was a member but is no more a -+ * member of this group. - */ -- ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); -+ ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, 1); -+ "removing group member", -+ user_name, AUDIT_NO_ID, 1); - #endif -- SYSLOG ((LOG_INFO, "add '%s' to group '%s'", -- user_newname, ngrp->gr_name)); -+ SYSLOG ((LOG_INFO, -+ "delete '%s' from group '%s'", -+ user_name, ngrp->gr_name)); - } -- if (!changed) -- goto free_ngrp; -+ } else if (is_member) { -+ /* User was not a member but is now a member this -+ * group. -+ */ -+ 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); -+#endif -+ SYSLOG ((LOG_INFO, "add '%s' to group '%s'", -+ user_newname, ngrp->gr_name)); -+ } -+ if (!changed) -+ goto free_ngrp; - -- if (gr_update (ngrp) == 0) { -- fprintf (stderr, -- _("%s: failed to prepare the new %s entry '%s'\n"), -- Prog, gr_dbname (), ngrp->gr_name); -- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); -- fail_exit (E_GRP_UPDATE); -- } -+ if (gr_update (ngrp) == 0) { -+ fprintf (stderr, -+ _("%s: failed to prepare the new %s entry '%s'\n"), -+ Prog, gr_dbname (), ngrp->gr_name); -+ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); -+ fail_exit (E_GRP_UPDATE); -+ } - - free_ngrp: -- gr_free(ngrp); -- } -+ gr_free(ngrp); - } - -+ - #ifdef SHADOWGRP - static void - update_gshadow_file(void) --- -2.45.1 - - -From d8e6a8b99b4d844328d875287babf6e13860d464 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:29:46 +0200 -Subject: [PATCH 16/16] src/usermod.c: update_gshadow(): Add helper function - -Keep the while loop in the outer function, and move the iteration code -to this new helper. This makes it a bit more readable. - -Cc: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 223 ++++++++++++++++++++++++++------------------------ - 1 file changed, 116 insertions(+), 107 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 4ea11376..f8896984 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -183,6 +183,7 @@ static void update_group(const struct group *grp); - - #ifdef SHADOWGRP - static void update_gshadow_file(void); -+static void update_gshadow(const struct sgrp *sgrp); - #endif - static void grp_update (void); - -@@ -814,141 +815,149 @@ update_gshadow_file(void) - * Scan through the entire shadow group file looking for the groups - * that the user is a member of. - */ -- while ((sgrp = sgr_next ()) != NULL) { -- bool changed; -- bool is_member; -- bool was_member; -- bool was_admin; -- struct sgrp *nsgrp; -+ while ((sgrp = sgr_next()) != NULL) -+ update_gshadow(sgrp); -+} -+#endif /* SHADOWGRP */ - -- changed = false; - -- /* -- * See if the user was a member of this group -- */ -- was_member = is_on_list (sgrp->sg_mem, user_name); -+#ifdef SHADOWGRP -+static void -+update_gshadow(const struct sgrp *sgrp) -+{ -+ bool changed; -+ bool is_member; -+ bool was_member; -+ bool was_admin; -+ struct sgrp *nsgrp; - -- /* -- * See if the user was an administrator of this group -- */ -- was_admin = is_on_list (sgrp->sg_adm, user_name); -+ changed = false; - -- /* -- * See if the user specified this group as one of their -- * concurrent groups. -- */ -- is_member = Gflg && ( (was_member && aflg) -- || is_on_list (user_groups, sgrp->sg_name)); -+ /* -+ * See if the user was a member of this group -+ */ -+ was_member = is_on_list (sgrp->sg_mem, user_name); - -- if (!was_member && !was_admin && !is_member) { -- continue; -- } -+ /* -+ * See if the user was an administrator of this group -+ */ -+ was_admin = is_on_list (sgrp->sg_adm, user_name); - -- /* -- * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted -- * groups while leaving the user apart of groups not mentioned -- */ -- if (Gflg && rflg) { -- is_member = !is_member; -- } -+ /* -+ * See if the user specified this group as one of their -+ * concurrent groups. -+ */ -+ is_member = Gflg && ( (was_member && aflg) -+ || is_on_list (user_groups, sgrp->sg_name)); - -- nsgrp = __sgr_dup (sgrp); -- if (NULL == nsgrp) { -- fprintf (stderr, -- _("%s: Out of memory. Cannot update %s.\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -+ if (!was_member && !was_admin && !is_member) -+ return; - -- if (was_admin && lflg) { -- /* User was an admin of this group but the user -- * has been renamed. -- */ -- nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); -- 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); --#endif -- SYSLOG ((LOG_INFO, -- "change admin '%s' to '%s' in shadow group '%s'", -- user_name, user_newname, nsgrp->sg_name)); -- } -- -- if (was_member) { -- if ((!Gflg) || is_member) { -- /* User was a member and is still a member -- * of this group. -- * But the user might have been renamed. -- */ -- if (lflg) { -- nsgrp->sg_mem = del_list (nsgrp->sg_mem, -- user_name); -- nsgrp->sg_mem = add_list (nsgrp->sg_mem, -- user_newname); -- changed = true; -+ /* -+ * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted -+ * groups while leaving the user apart of groups not mentioned -+ */ -+ if (Gflg && rflg) { -+ is_member = !is_member; -+ } -+ -+ nsgrp = __sgr_dup (sgrp); -+ if (NULL == nsgrp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot update %s.\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+ if (was_admin && lflg) { -+ /* User was an admin of this group but the user -+ * has been renamed. -+ */ -+ nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); -+ nsgrp->sg_adm = add_list (nsgrp->sg_adm, 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 (AUDIT_USER_CHAUTHTOK, Prog, -+ "changing admin name in shadow group", -+ user_name, AUDIT_NO_ID, 1); - #endif -- SYSLOG ((LOG_INFO, -- "change '%s' to '%s' in shadow group '%s'", -- user_name, user_newname, -- nsgrp->sg_name)); -- } -- } else { -- /* User was a member but is no more a -- * member of this group. -- */ -- nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); -+ SYSLOG ((LOG_INFO, -+ "change admin '%s' to '%s' in shadow group '%s'", -+ user_name, user_newname, nsgrp->sg_name)); -+ } -+ -+ if (was_member) { -+ if ((!Gflg) || is_member) { -+ /* User was a member and is still a member -+ * of this group. -+ * But the user might have been renamed. -+ */ -+ if (lflg) { -+ nsgrp->sg_mem = del_list (nsgrp->sg_mem, -+ user_name); -+ nsgrp->sg_mem = add_list (nsgrp->sg_mem, -+ user_newname); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing user from shadow group", -- user_name, AUDIT_NO_ID, 1); -+ "changing member in shadow group", -+ user_name, AUDIT_NO_ID, 1); - #endif - SYSLOG ((LOG_INFO, -- "delete '%s' from shadow group '%s'", -- user_name, nsgrp->sg_name)); -+ "change '%s' to '%s' in shadow group '%s'", -+ user_name, user_newname, -+ nsgrp->sg_name)); - } -- } else if (is_member) { -- /* User was not a member but is now a member this -- * group. -+ } else { -+ /* User was a member but is no more a -+ * member of this group. - */ -- nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); -+ nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to shadow group", -- user_newname, AUDIT_NO_ID, 1); -+ "removing user from shadow group", -+ user_name, AUDIT_NO_ID, 1); - #endif -- SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", -- user_newname, nsgrp->sg_name)); -+ SYSLOG ((LOG_INFO, -+ "delete '%s' from shadow group '%s'", -+ user_name, nsgrp->sg_name)); - } -- if (!changed) -- goto free_nsgrp; -- -- /* -- * Update the group entry to reflect the changes. -+ } else if (is_member) { -+ /* User was not a member but is now a member this -+ * group. - */ -- if (sgr_update (nsgrp) == 0) { -- fprintf (stderr, -- _("%s: failed to prepare the new %s entry '%s'\n"), -- Prog, sgr_dbname (), nsgrp->sg_name); -- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", -- sgr_dbname (), nsgrp->sg_name)); -- fail_exit (E_GRP_UPDATE); -- } -+ 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); -+#endif -+ SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", -+ user_newname, nsgrp->sg_name)); -+ } -+ if (!changed) -+ goto free_nsgrp; - --free_nsgrp: -- free (nsgrp); -+ /* -+ * Update the group entry to reflect the changes. -+ */ -+ if (sgr_update (nsgrp) == 0) { -+ fprintf (stderr, -+ _("%s: failed to prepare the new %s entry '%s'\n"), -+ Prog, sgr_dbname (), nsgrp->sg_name); -+ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", -+ sgr_dbname (), nsgrp->sg_name)); -+ fail_exit (E_GRP_UPDATE); - } -+ -+free_nsgrp: -+ free (nsgrp); - } - #endif /* SHADOWGRP */ - -+ - /* - * grp_update - add user to secondary group set - * --- -2.45.1 - diff --git a/shadow-4.15.1-useradd-fix-write-full-return.patch b/shadow-4.15.1-useradd-fix-write-full-return.patch deleted file mode 100644 index 64e2ef8..0000000 --- a/shadow-4.15.1-useradd-fix-write-full-return.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 8903b94c86c978e8abef623358fd3e4629c06967 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 9 Sep 2024 10:36:17 +0200 -Subject: [PATCH] useradd: fix write_full() return value - -write_full() returns -1 on error and useradd was checking another value. - -Closes: https://github.com/shadow-maint/shadow/issues/1072 -Fixes: f45498a6c286 ("libmisc/write_full.c: Improve write_full()") - -Reported-by: -Suggested-by: -Reviewed-by: Alejandro Colomar -Reviewed-by: Iker Pedrosa ---- - src/useradd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 02c500d0..d64fd892 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2042,7 +2042,7 @@ static void lastlog_reset (uid_t uid) - return; - } - if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) -- || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll)) -+ || (write_full (fd, &ll, sizeof (ll)) == -1) - || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to reset the lastlog entry of UID %lu: %s\n"), --- -2.46.0 - diff --git a/shadow-utils-configure-gshadow.patch b/shadow-utils-configure-gshadow.patch deleted file mode 100644 index a983ce0..0000000 --- a/shadow-utils-configure-gshadow.patch +++ /dev/null @@ -1,20 +0,0 @@ -The missing #include causes the configure check to fail -spuriously, resulting in HAVE_SHADOWGRP not being defined. - -Submitted upstream: - -diff --git a/configure.ac b/configure.ac -index 924254a0c8171802..6c7d9839979e037d 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -116,6 +116,10 @@ if test "$ac_cv_header_shadow_h" = "yes"; then - ac_cv_libc_shadowgrp, - AC_RUN_IFELSE([AC_LANG_SOURCE([ - #include -+ #ifdef HAVE_GSHADOW_H -+ #include -+ #endif -+ int - main() - { - struct sgrp *sg = sgetsgent("test:x::"); diff --git a/shadow-utils.spec b/shadow-utils.spec index 06717e1..7bc7e8b 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.15.1 -Release: 12%{?dist} +Version: 4.20.0 +Release: 1%{?dist} Epoch: 2 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/v%{version}/shadow-%{version}.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz.asc +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 @@ -16,22 +16,10 @@ Source7: passwd.pamd ### Globals ### %global includesubiddir %{_includedir}/shadow +# Fail linking if there are undefined symbols. +%global _ld_strict_symbol_defs 1 ### Patches ### -# Misc manual page changes - non-upstreamable -Patch0: shadow-4.15.0-manfix.patch -# Date parsing improvement - could be upstreamed -Patch1: shadow-4.15.0-date-parsing.patch -# Several patches already available upstream. PRs:#994, #996, #997 -Patch2: shadow-4.15.1-sast-fixes.patch -# Audit message changes - partially upstreamed -Patch3: shadow-4.15.1-audit-update.patch -# Probably non-upstreamable -Patch4: shadow-4.15.0-account-tools-setuid.patch -# https://github.com/shadow-maint/shadow/commit/ead55e9ba8958504e23e29545f90c4dd925c7462 -Patch5: shadow-4.15.0-getdef-spurious-error.patch -# https://github.com/shadow-maint/shadow/commit/8903b94c86c978e8abef623358fd3e4629c06967 -Patch6: shadow-4.15.1-useradd-fix-write-full-return.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -53,12 +41,15 @@ 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 ### @@ -86,16 +77,14 @@ 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 -License: BSD and GPLv2+ %description subid Utility library that provides a way to manage subid ranges. @@ -103,14 +92,13 @@ Utility library that provides a way to manage subid ranges. %package subid-devel Summary: Development package for shadow-utils-subid -License: BSD and GPLv2+ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} %description subid-devel Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-%{version} +%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 @@ -118,25 +106,12 @@ cp -f doc/HOWTO.utf8 doc/HOWTO cp -a %{SOURCE4} %{SOURCE5} . cp -a %{SOURCE6} man/login.defs.d/HOME_MODE.xml -# Force regeneration of getdate.c -rm lib/getdate.c - %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 \ - --disable-account-tools-setuid \ - --enable-lastlog \ - --enable-logind=no \ - --enable-man \ + --disable-account-tools-setuid \ + --enable-logind=no \ + --enable-man \ --enable-shadowgrp \ --enable-shared \ --with-audit \ @@ -148,16 +123,21 @@ autoreconf --with-yescrypt \ --without-libbsd \ --without-libcrack \ - --without-nscd \ + --without-nscd \ --without-sssd %make_build +%check +make check + %install %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 @@ -175,31 +155,20 @@ mv -v $RPM_BUILD_ROOT/usr/sbin/* $RPM_BUILD_ROOT%{_bindir}/ # 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}/su rm $RPM_BUILD_ROOT%{_bindir}/faillog -rm $RPM_BUILD_ROOT%{_sbindir}/logoutd 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/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/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}/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}/man3/getspnam.* @@ -211,11 +180,8 @@ 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}/chpasswd rm $RPM_BUILD_ROOT%{_pam_confdir}/chsh -rm $RPM_BUILD_ROOT%{_pam_confdir}/groupmems rm $RPM_BUILD_ROOT%{_pam_confdir}/login -rm $RPM_BUILD_ROOT%{_pam_confdir}/newusers rm $RPM_BUILD_ROOT%{_pam_confdir}/su find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete @@ -242,11 +208,12 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %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(0755,root,root) %caps(cap_setgid=ep) %{_bindir}/newgidmap %attr(0755,root,root) %caps(cap_setuid=ep) %{_bindir}/newuidmap @@ -284,7 +251,6 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_mandir}/man8/chgpasswd.8* %{_mandir}/man8/newusers.8* %{_mandir}/man8/*conv.8* -%{_mandir}/man8/lastlog.8* %{_mandir}/man8/vipw.8* %{_mandir}/man8/vigr.8* @@ -298,12 +264,119 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog -* Thu Oct 10 2024 Iker Pedrosa - 2:4.15.1-12 +* 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 -* Wed Sep 18 2024 Iker Pedrosa - 2:4.15.1-10 +* 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. diff --git a/sources b/sources index ca5a1c9..7669083 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.15.1.tar.xz) = 2667a1d781066adce42e684463329c3f32d28c07b7b79b628525bffcd61c078f6ff430be3d42976d0509d9f9a55cd80f5a50d479b85155476cee7f00f06708d8 -SHA512 (shadow-4.15.1.tar.xz.asc) = 0a39d6a45b7d8df12aade89ed9fc9d481c91297dbd34e85fe831426c1d0051cbcf8478759306b8871cd6b1835604c5836decf398d0165c50ac52fee365561446 +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/* diff --git a/tests/sanity/Makefile b/tests/sanity/Makefile deleted file mode 100644 index 386221b..0000000 --- a/tests/sanity/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2006 Red Hat, Inc. All rights reserved. This copyrighted material -# is made available to anyone wishing to use, modify, copy, or -# redistribute it subject to the terms and conditions of the GNU General -# Public License v.2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# Author: Jakub Hrozek - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# -# Example Makefile for RHTS # -# This example is geared towards a test for a specific package # -# It does most of the work for you, but may require further coding # -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# - -# The toplevel namespace within which the test lives. -TOPLEVEL_NAMESPACE=CoreOS - -# The name of the package under test: -PACKAGE_NAME=shadow-utils - -# The path of the test below the package: -RELATIVE_PATH=sanity - -# Version of the Test. Used with make tag. -export TESTVERSION=1.1 - -# The combined namespace of the test. -export TEST=/$(TOPLEVEL_NAMESPACE)/$(PACKAGE_NAME)/$(RELATIVE_PATH) - -# A phony target is one that is not really the name of a file. -# It is just a name for some commands to be executed when you -# make an explicit request. There are two reasons to use a -# phony target: to avoid a conflict with a file of the same -# name, and to improve performance. -.PHONY: all install download clean - -# Executables to be built should be added here, they will be generated on the system under test. -BUILT_FILES= - -# Data files, .c files, scripts anything needed to either compile the test and/or run it. -FILES=$(METADATA) Makefile PURPOSE sanity_test.py runtest.sh - -run: $(FILES) build - ./runtest.sh - -build: $(BUILT_FILES) - chmod a+x ./sanity_test.py - chmod a+x ./runtest.sh - -clean: - rm -f *~ *.rpm $(BUILT_FILES) - -# Include Common Makefile -include /usr/share/rhts/lib/rhts-make.include - -# Generate the testinfo.desc here: -$(METADATA): Makefile - @touch $(METADATA) - @echo "Owner: Jakub Hrozek " > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "License: GNU GPL" >> $(METADATA) - @echo "Description: Basic sanity test for shadow-utils" >> $(METADATA) - @echo "TestTime: 5m" >> $(METADATA) - @echo "RunFor: $(PACKAGE_NAME)" >> $(METADATA) - @echo "Requires: $(PACKAGE_NAME)" >> $(METADATA) - @echo "Requires: python" >> $(METADATA) - rhts-lint $(METADATA) - diff --git a/tests/sanity/PURPOSE b/tests/sanity/PURPOSE deleted file mode 100644 index 27062e1..0000000 --- a/tests/sanity/PURPOSE +++ /dev/null @@ -1,10 +0,0 @@ -This is a basic sanity test for the shadow-utils package. It is implemented -in python on top of the unittesting.py module. - -Its purpose is to ensure that the binaries in the shadow-utils package behave -as expected and its switches/options work correctly. - -For the most part, every binary in the shadow-utils package is represented by -a single class named Test, i.e. TestUsermod etc. There are some -exceptions, like TestUseraddWeirdNameTest though. - diff --git a/tests/sanity/runtest.sh b/tests/sanity/runtest.sh deleted file mode 100755 index cb2a2b5..0000000 --- a/tests/sanity/runtest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -. /usr/bin/rhts-environment.sh -. /usr/share/beakerlib/beakerlib.sh || exit 1 - -rlJournalStart -rlFileBackup --clean /etc/default/useradd- /etc/default/useradd -setenforce 0 -python sanity_test.py -v -setenforce 1 -rlFileRestore - -EXIT=$? -if [[ $EXIT -eq 0 ]]; then - RESULT="PASS" -else - RESULT="FAIL" -fi - - -rlJournalEnd - -echo "Result: $RESULT" -echo "Exit: $EXIT" -report_result $TEST $RESULT $EXIT diff --git a/tests/sanity/sanity_test.py b/tests/sanity/sanity_test.py deleted file mode 100755 index e9c45c2..0000000 --- a/tests/sanity/sanity_test.py +++ /dev/null @@ -1,1013 +0,0 @@ -#!/usr/bin/env python -""" -A script that tests functionality of the shadow-utils package. - -Author: Jakub Hrozek, -License: GNU GPL v2 -Date: 2007 - -TODO: - * tests for password aging - * if something fails, print out the command issued for easier debugging - * test long options variants along with the short ones -""" - -import unittest -import pwd -import grp -import commands -import os -import os.path -import sys -import copy -import tempfile -import rpm -import shutil - -from UserDict import UserDict - -class RedHatVersion(object): - def __init__(self, type=None, version=None, release=None): - self.type = type - self.version = version - self.release = release - self.rhel = False - - def __eq__( self, other): - """ - Don't compare if either of the values is None - so we can do comparisons like 'is it fedora?' or 'is it rhel4?' - """ - ok = (self.type == other.type) - if ok == False: return False - - if self.version and other.version: - ok = (self.version == other.version) - if ok == False: return False - - if (self.release == other.release): - ok = (self.release == other.release) - - return ok - - def __ne__( self, other): - return not self.__eq__(other) - - def __get_fedora_info(self, mi): - return [ (h['version'],h['release']) for h in mi ][0] - - def __get_rhel_info(self, mi): - # The rules for RHEL versions are braindead..releases even more - ver_rpm, rel_rpm = [ (h['version'],h['release']) for h in mi ][0] - rhel_versions = { '3AS' : 3, '4AS' : 4, '5Server' : 5, '5Client' : 5, '6' : 6 } - if ver_rpm[:3] == '5.9' or ver_rpm[:1] == '6': # rhel6 prerelease and release hack - rhel_versions[ver_rpm] = 6 - if ver_rpm in rhel_versions.keys(): - return (rhel_versions[ver_rpm], rel_rpm) - - def is_rhel(self): - return self.rhel - - def get_info(self): - """ - Returns a tuple containing (type, version, release) of RHEL or Fedora. - Type is either RHEL or Fedora. - Returns None if it cannot parse the info - """ - - ts = rpm.TransactionSet() - mi = ts.dbMatch() - mi.pattern('name', rpm.RPMMIRE_GLOB, 'redhat-release*') - - if mi: - self.rhel = True - return ('RHEL',) + self.__get_rhel_info(mi) - else: - mi = ts.dbMatch('name','fedora-release') - self.rhel = False - if mi.count() != 0: - return ('Fedora',) + self.__get_fedora_info(mi) - - return None - - -class UserInfo(UserDict): - fields = { "pw_name" : 0, "pw_passwd" : 1, "pw_uid" : 2, "pw_gid" : 3, - "pw_gecos" : 4, "pw_dir" : 5, "pw_shell" : 6 } - - def __init__(self): - UserDict.__init__(self) - for f in UserInfo.fields: self[f] = None - - def __getitem__(self, key): - return UserDict.__getitem__(self, key) - - def __setitem__(self, key, value): - UserDict.__setitem__(self, key, value) - - def __cmp__(self, other): - return UserDict.__cmp__(self, other) - - def __repr__(self): - return " ; ".join( [ "%s => %s" % (k, v) for k, v in self.data.items() ] ) - - def __parse_info(self, struct): - for f in UserInfo.fields: - self[f] = struct[UserInfo.fields[f]] - - def get_info_uid(self, uid): - self.__parse_info(pwd.getpwuid(uid)) - - def get_info_name(self, name): - try: - self.__parse_info(pwd.getpwnam(name)) - except KeyError: - return None - - def lazy_compare(self, pattern): - """ Compare pattern against self. If any field in pattern is set - to None, it is automatically considered equal with the corresponding - field in self. """ - for field in UserInfo.fields: - if pattern[field] and pattern[field] != self[field]: - return False - - return True - -class GroupInfo(UserDict): - fields = { "gr_name" : 0, "gr_passwd" : 1, - "gr_gid" : 2, "gr_mem" : 3} - - def __init__(self): - UserDict.__init__(self) - for f in GroupInfo.fields: self[f] = None - - def __getitem__(self, key): - return UserDict.__getitem__(self, key) - - def __setitem__(self, key, value): - UserDict.__setitem__(self, key, value) - - def __cmp__(self, other): - return UserDict.__cmp__(self, other) - - def __repr__(self): - return " ; ".join( [ "%s => %s" % (k, v) for k, v in self.data.items() ] ) - - def __parse_info(self, struct): - for f in GroupInfo.fields: - self[f] = struct[GroupInfo.fields[f]] - - def get_info_gid(self, gid): - self.__parse_info(grp.getgrgid(gid)) - - def get_info_name(self, name): - self.__parse_info(grp.getgrnam(name)) - - def lazy_compare(self, pattern): - """ Compare pattern against self. If any field in pattern is set - to None, it is automatically considered equal with the corresponding - field in self. """ - for field in GroupInfo.fields: - if pattern[field] and pattern[field] != self[field]: - return False - - return True - -class LoginDefsParser(UserDict): - "A quick-n-dirty way how to fetch the defaults from /etc/login.defs into a dictionary" - - def __getitem__(self, key): - try: - return UserDict.__getitem__(self, key) - except KeyError: - # if a name-value is not defined in the config file, return defaults - if key == "CREATE_MAIL_SPOOL": - return "yes" - if key == "UMASK": - return "077" - - def __init__(self, path="/etc/login.defs",split=None): - self.path = path - UserDict.__init__(self) - try: - defs = open(path) - except IOError: - print "Could not open the config file %s" % (path) - - for line in defs: - if line.startswith('#'): continue - fields = line.split(split) - if len(fields) != 2: continue # yeah, we're dirty - self.data[fields[0]] = fields[1] - - def serialize(self): - output = open(self.path, "w+") - for k,v in self.data.items(): - output.write("%s=%s" % (k, v)) - - output.write("\n") - output.close() - -class TestUserInfo(unittest.TestCase): - def testLazyCompare(self): - """ (test sanity): Test comparing two UserInfo records """ - a = UserInfo() - a["pw_name"] = "foo" - a["pw_uid"] = 555 - b = copy.deepcopy(a) - c = UserInfo() - - self.assertEqual(a.lazy_compare(b), True) - self.assertEqual(a.lazy_compare(c), True) - - c["pw_name"] = "foo" - c["pw_uid"] = None - self.assertEqual(a.lazy_compare(c), True) - self.assertEqual(c.lazy_compare(a), False) - - c["pw_name"] = "bar" - self.assertNotEqual(a.lazy_compare(c), True) - - def testGetInfoUid(self): - """ (test sanity): Test getting user info based on his UID """ - a = UserInfo() - a.get_info_uid(0) - self.assertEqual(a["pw_name"], "root") - - def testGetInfoName(self): - """ (test sanity): Test getting user info based on his name """ - a = UserInfo() - a.get_info_name("root") - self.assertEqual(a["pw_uid"], 0) - -class ShadowUtilsTestBase: - """ Handy routines """ - def getDefaults(self): - # get the default values for so we can compare against that - (status, defaults_str) = commands.getstatusoutput('useradd -D') - if status != 0: - raise RuntimeError("Could not get the default values for useradd") - return dict([ rec.split("=") for rec in defaults_str.split("\n") ]) - - def getDefaultUserInfo(self, username): - expected = UserInfo() - defaults = self.getDefaults() - - expected["pw_name"] = username - expected["pw_dir"] = defaults["HOME"] + "/" + username - expected["pw_shell"] = defaults["SHELL"] - - return expected - -class TestUseradd(ShadowUtilsTestBase, unittest.TestCase): - def setUp(self): - self.username = "test-shadow-utils-useradd" - - def tearDown(self): - commands.getstatusoutput("userdel -r %s" % (self.username)) - - def testBasicAdd(self): - """ useradd: Tests basic adding of a user """ - expected = self.getDefaultUserInfo(self.username) - - runme = "useradd %s" % (self.username) - (status, output) = commands.getstatusoutput(runme) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user\nIssued command: %s" % (runme)) - - def testExistingUser(self): - """ useradd: Test that user with an existing name cannot be added """ - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - self.assertNotEqual(commands.getstatusoutput("useradd %s" % (self.username))[0], 0, "FAIL: User that already exists added") - - def testCustomUID(self): - """ useradd: Adding an user with a specific UID """ - UID = 23456 # FIXME - test for a free UID slot first - - expected = self.getDefaultUserInfo(self.username) - expected["pw_uid"] = UID - - runme = "useradd %s -u %d" % (self.username, UID) - (status, output) = commands.getstatusoutput(runme) - self.failUnlessEqual(status, 0, "Issued command: %s\n" % (runme) + "Got from useradd: %s\n" % (output)) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific UID\nIssued command: %s" % (runme)) - - def testNegativeUID(self): - """ useradd: Tests that user cannot have a negative UID assigned """ - self.assertNotEqual(commands.getstatusoutput("useradd %s --uid -5" % (self.username))[0], 0, "FAIL: User with UID < 0 added") - - def testCustomExistingUID(self): - """ useradd: Adding a user with a specific existing UID """ - UID = 32112 - - expected = self.getDefaultUserInfo(self.username) - expected["pw_uid"] = UID - - (status_u, output_u) = commands.getstatusoutput("useradd %s -u %d" % (self.username, UID)) - - # must fail without -o flag - (status_u_no_o, output_u_no_o) = commands.getstatusoutput("useradd foo -u %d" % (UID)) - - # must pass with -o flag - (status_o, output_o) = commands.getstatusoutput("useradd foo -u %d -o" % (UID)) - - # clean up - (status, output) = commands.getstatusoutput("userdel -r foo") - - self.failUnlessEqual(status_u, 0, "FAIL: cannot add an user with a specified UID\n"+output_u) - self.assertEqual(status_o, 0, "FAIL: cannot add an user with an existing UID using the -o flag\n"+output_o) - self.failUnlessEqual(status, 0, output) - self.assertNotEqual(status_u_no_o, 0, "FAIL: user with an existing UID added\n"+output_u_no_o) - - def testCustomGID(self): - """ useradd: Adding an user with a specific GID """ - GID = 100 # users group should be everywhere - should we test before? - expected = self.getDefaultUserInfo(self.username) - expected["pw_gid"] = GID - - (status, output) = commands.getstatusoutput("useradd %s -g %d" % (self.username, GID)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific GID") - - def testCustomShell(self): - """ useradd: Adding an user with a specific login shell """ - shell = "/bin/ksh" - expected = self.getDefaultUserInfo(self.username) - expected["pw_shell"] = shell - - (status, output) = commands.getstatusoutput("useradd %s -s %s" % (self.username, shell)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific shell") - - def testCustomHome(self): - """ useradd: Adding an user with a specific home directory """ - home = "/tmp/useradd-test" - os.mkdir(home) - expected = self.getDefaultUserInfo(self.username) - expected["pw_dir"] = home - - (status, output) = commands.getstatusoutput("useradd %s -d %s" % (self.username, home)) - shutil.rmtree(home) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific home") - - def testSystemAccount(self): - """ useradd: Adding a system user (UID < UID_MIN from /etc/login.defs) """ - defaults = LoginDefsParser() - - # system account with no home dir - expected = self.getDefaultUserInfo(self.username) - - (status, output) = commands.getstatusoutput("useradd -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(os.path.exists(created["pw_dir"]), False, "FAIL: System user has a home dir created") - self.assertEqual(created["pw_uid"] < defaults['UID_MIN'], True, "FAIL: System user has UID > UID_MIN") - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a system user") - - def testAddToMoreGroups(self): - """ useradd: Creating an user that belongs to more than one group """ - (status, output) = commands.getstatusoutput("useradd -G bin %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - gr_bin = GroupInfo() - gr_bin.get_info_name("bin") - self.assertEqual(self.username in gr_bin["gr_mem"], True, "FAIL: User not in supplementary group after usermod -G -a") - - - def testAddWithCommonName(self): - """ useradd: Specifying a comment (user for account name) """ - comment = "zzzzzz" - (status, output) = commands.getstatusoutput("useradd -c %s %s" % (comment, self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created["pw_gecos"], comment, "FAIL: failed to create a user with a GECOS comment") - - def testHomePermissions(self): - """ useradd: Check if permissions on newly created home dir match the umask """ - defaults = LoginDefsParser() - - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - - import stat - perm = os.stat(created["pw_dir"])[stat.ST_MODE] - mode = int(oct(perm & 0777)) - - self.assertEqual(defaults["UMASK"], "077", "FAIL: umask setting is not sane - is %s, should be 077" % (defaults["UMASK"])) - self.assertEqual(int(defaults["UMASK"]) + mode , 777, "FAIL: newly-created home dir does not match the umask") - - def testCreateMailSpool(self): - """ useradd: Check whether the mail spool gets created when told to""" - # set up creating of mail spool - defaults = LoginDefsParser("/etc/default/useradd", split="=") - - create_mail = defaults["CREATE_MAIL_SPOOL"] - defaults["CREATE_MAIL_SPOOL"] = "yes" - defaults.serialize() - - login_defs = LoginDefsParser() - - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - # clean up - defaults["CREATE_MAIL_SPOOL"] = create_mail - defaults.serialize() - self.assertEqual(os.path.exists(login_defs["MAIL_DIR"] + "/" + self.username), True, "FAIL: useradd did not create mail spool") - - def testDefaultMailSettings(self): - """ useradd: Check whether the mail spool is on by default""" - defaults = LoginDefsParser("/etc/default/useradd", split="=") - self.assertEqual(defaults["CREATE_MAIL_SPOOL"], "yes\n") - - def testNoLastlog(self): - """ useradd: Check if the -l option prevents from being added to the lastlog """ - pass # FIXME - add some code here - - -class TestUseraddWeirdNameTest(unittest.TestCase, ShadowUtilsTestBase): - """ Tests addition/removal of usernames that have proven to be problematic in the past. - The reason to separate these from the main useradd test suite is to not run the setUp - and tearDown methods """ - - def addAndRemove(self, username, success=True): - expected = self.getDefaultUserInfo(username) - expected["pw_name"] = username - - (status, output) = commands.getstatusoutput("useradd %s" % (username)) - if success: - self.failUnlessEqual(status, 0, output) - else: - self.failIfEqual(status, 0, output) - return True - - created = UserInfo() - created.get_info_name(username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: TestUseraddWeirdName::addAndRemove - could not add a user") - - # the cleanup method won't help this time - (status, output) = commands.getstatusoutput("userdel -r %s" % (username)) - self.failUnlessEqual(status, 0, output) - - def testNumericName(self): - """ useradd: Test if an user with a purely numerical name can be added (123) """ - return self.addAndRemove("123") - - def testSambaName(self): - """ useradd: Test if an user with a name with a dollar at the end can be added (joepublic$ ) """ - return self.addAndRemove("joepublic$") - - def testDotInName(self): - """ useradd: Test if an user with a name with a dot in it can be added (joe.public ) """ - return self.addAndRemove("joe.public") - - def testAtInName(self): - """ useradd: Test if an user with an '@' in name can be added (joe@public.com) - should fail """ - return self.addAndRemove("joe@public.com", False) - - def testUppercase(self): - """ useradd: Test if an user with UPPERCASE or Uppercase name can be added """ - return self.addAndRemove("JOEPUBLIC") - return self.addAndRemove("Joepublic") - -class TestUseraddDefaultsChange(unittest.TestCase, ShadowUtilsTestBase): - def testDefaultsChange(self): - """ useradd: Test overriding default settings (shell, home dir, group) with a -D option """ - save = self.getDefaults() - - new_defs = dict() - new_defs["SHELL"] = "/bin/ksh" - new_defs["GROUP"] = "1" - new_defs["HOME"] = "/tmp" - - command = "useradd -D -s%s -g%s -b%s" % (new_defs["SHELL"], new_defs["GROUP"], new_defs["HOME"]) - (status, output) = commands.getstatusoutput(command) - self.failUnlessEqual(status, 0, output) - - overriden = self.getDefaults() - [ self.assertEqual(overriden[k], new_defs[k]) for k in new_defs.keys() ] - - command = "useradd -D -s%s -g%s -b%s" % (save["SHELL"], save["GROUP"], save["HOME"]) - (status, output) = commands.getstatusoutput(command) - self.failUnlessEqual(status, 0, output) - - -class TestUserdel(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.username = "test-shadow-utils-userdel" - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - def testRemoveUserGroup(self): - """ userdel: test if userdel removes user's group when he's deleted - regression test for #201379 """ - (status, output) = commands.getstatusoutput("userdel -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - # This would fail if we did not have the group removed - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("userdel -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - -class TestUsermod(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.username = "test-shadow-utils-usermod" - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - def tearDown(self): - (status, output) = commands.getstatusoutput("userdel -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - def testAppendToSupplementaryGroup(self): - """ usermod: Test if a user can be added to a supplementary group """ - add_group = "additional_group" - (status, output) = commands.getstatusoutput("groupadd %s" % (add_group)) - self.failUnlessEqual(status, 0, output) - - (status_mod, output_mod) = commands.getstatusoutput("usermod -a -G %s %s" % (add_group, self.username)) - add_group_info = GroupInfo() - add_group_info.get_info_name(add_group) - (status, output) = commands.getstatusoutput("groupdel %s" % (add_group)) - - self.failUnlessEqual(status, 0, output) - self.failUnlessEqual(status_mod, 0, output_mod) - self.assertEqual(self.username in add_group_info["gr_mem"], True, "User not in supplementary group after usermod -G --append") - - - def testAppendToSupplementaryGroupLongOption(self): - """ usermod: Test if a user can be added to a supplementary group via --append rather that -a (regression test for 222540) """ - # this is known to not work on older RHELs - test what we are running - rhv = RedHatVersion() - runs = rhv.get_info() - if rhv.is_rhel(): - if runs[1] < 5: - print "This test makes sense for RHEL5+" - return - else: - if runs[1] < 6: - print "This test makes sense for Fedora 6+" - return - - type, release, version = RedHatVersion().get_info() - if RedHatVersion().is_rhel(): - if release < 5 or (release == 5 and version < 2): - print "This test makes sense for RHEL 5.2+" - return - - add_group = "additional_group" - (status, output) = commands.getstatusoutput("groupadd %s" % (add_group)) - self.failUnlessEqual(status, 0, output) - - (status_mod, output_mod) = commands.getstatusoutput("usermod --append -G %s %s" % (add_group, self.username)) - add_group_info = GroupInfo() - add_group_info.get_info_name(add_group) - (status, output) = commands.getstatusoutput("groupdel %s" % (add_group)) - - self.failUnlessEqual(status, 0, output) - self.failUnlessEqual(status_mod, 0, output_mod) - self.assertEqual(self.username in add_group_info["gr_mem"], True, "User not in supplementary group after usermod -G --append") - - - def testNameChange(self): - """ usermod: Test if the comment field (used as the Common Name) can be changed """ - new_comment = "zzzzzz" - - (status, output) = commands.getstatusoutput("usermod -c %s %s" % (new_comment, self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - - self.assertEqual(created["pw_gecos"], new_comment) - - def testHomeChange(self): - """ usermod: Test if user's home directory can be changed """ - new_home = "/tmp" - created = UserInfo() - created.get_info_name(self.username) - old_home = created["pw_dir"] - - (status, output) = commands.getstatusoutput("usermod -d %s %s" % (new_home, self.username)) - self.failUnlessEqual(status, 0, output) - - created.get_info_name(self.username) - self.assertEqual(created["pw_dir"], new_home) - - # revert to old home so we can userdel -r in tearDown - (status, output) = commands.getstatusoutput("usermod -d %s %s" % (old_home, self.username)) - self.failUnlessEqual(status, 0, output) - - # FIXME - test if contents of /home directories are transferred with the -m option - # FIXME - test if new home is created if does not exist before - - def testGIDChange(self): - """ usermod: Test if user's gid can be changed. """ - new_group = "root" - # test non-existing group - (status_fail, output_fail) = commands.getstatusoutput("usermod -g no-such-group %s" % (self.username)) - (status, output) = commands.getstatusoutput("usermod -g %s %s" % (new_group, self.username)) - - created = UserInfo() - created.get_info_name(self.username) - - left = GroupInfo() - if left.get_info_name(self.username) == None: - (status_del, output_del) = commands.getstatusoutput("groupdel %s" % (self.username)) - self.failUnlessEqual(status_del, 0, output_del) - - self.failIfEqual(status_fail, 0, output_fail) - self.failUnlessEqual(status, 0, output) - self.assertEqual(created["pw_gid"], 0) #0 is root group - - def testLoginChange(self): - """ usermod: Test if user's login can be changed """ - new_login = "usermod-login-change" - user = UserInfo() - user.get_info_name(self.username) - uid = user["pw_uid"] # UID won't change even when login does - - # test changing to an existing user name - (status, output) = commands.getstatusoutput("usermod -l root %s" % (self.username)) - self.failIfEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("usermod -l %s %s" % (new_login, self.username)) - self.failUnlessEqual(status, 0, output) - user.get_info_name(new_login) - self.assertEqual(user["pw_uid"], uid) - - # revert so we can userdel -r on tearDown - (status, output) = commands.getstatusoutput("usermod -l %s %s" % (self.username, new_login)) - self.failUnlessEqual(status, 0, output) - - def testShellChange(self): - """ usermod: Test if user's shell can be changed """ - new_shell = "/bin/sh" - - (status, output) = commands.getstatusoutput("usermod -s %s %s" % (new_shell, self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created["pw_shell"], new_shell) - -class TestGroupadd(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.groupname = "test-shadow-utils-groups" - - def tearDown(self): - commands.getstatusoutput("groupdel %s" % (self.groupname)) - - def testAddGroup(self): - """ groupadd: Basic adding of a group """ - - expected = GroupInfo() - expected["gr_name"] = self.groupname - - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a group") - - def testAddSystemGroup(self): - """ groupadd: Adding a system group with gid < MIN_GID """ - - expected = GroupInfo() - expected["gr_name"] = self.groupname - defaults = LoginDefsParser() - - (status, output) = commands.getstatusoutput("groupadd -r %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(created["gr_gid"] < defaults["GID_MIN"], True, "FAIL: System group has gid >= GID_MIN") - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a system group") - - def testAddExistingGid(self): - """ groupadd: Test if we group with an existing GID can be added """ - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - gname = "%s-2" % (self.groupname) - - created = GroupInfo() - created.get_info_name(self.groupname) - - # no -o option -> this should fail - (status, output) = commands.getstatusoutput("groupadd -g%s %s" % (created["gr_gid"], gname)) - self.failIfEqual(status, 0, output) - - # override with -o option, should pass now - (status, output) = commands.getstatusoutput("groupadd -g%s -o %s" % (created["gr_gid"], gname)) - self.failUnlessEqual(status, 0, output) - - # test if the new GID is really the same - same_gid = GroupInfo() - same_gid.get_info_name(gname) - self.assertEqual(same_gid["gr_gid"], created["gr_gid"]) - - # clean up - (status, output) = commands.getstatusoutput("groupdel %s" % (gname)) - self.failUnlessEqual(status, 0, output) - - - def testOverrideDefaults(self): - """ groupadd: Test if the defaults can be overriden with the -K option """ - # this is known to not work on older RHELs - test what we are running - rhv = RedHatVersion() - runs = rhv.get_info() - if rhv.is_rhel(): - if runs[1] < 5: - print "This test makes sense for RHEL5+" - return - else: - if runs[1] < 6: - print "This test makes sense for Fedora 6+" - return - - - GID_MIN = 600 - GID_MAX = 625 - - (status, output) = commands.getstatusoutput("groupadd -K GID_MIN=%d -K GID_MAX=%d %s" % - (GID_MIN, GID_MAX, self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(GID_MIN <= created["gr_gid"] <= GID_MAX, True, "FAIL: created an user with UID of %d" % (created["gr_gid"])) - - - def testFOption(self): - """ groupadd: Tests the -f option of groupadd """ - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("groupadd -f %s" % (self.groupname)) - self.assertEqual(status, 0, output) - -class TestGroupaddInvalidName(unittest.TestCase, ShadowUtilsTestBase): - def testGroupaddInvalidName(self): - """ groupadd: Test adding of a group with an invalid name """ - (status, output) = commands.getstatusoutput("groupadd foo?") - self.assertNotEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupadd aaaaabbbbbcccccdddddeeeeefffffggg") #33 chars - self.assertNotEqual(status, 0, output) - -class TestGroupaddValidName(unittest.TestCase, ShadowUtilsTestBase): - def testGroupaddValidName(self): - """ groupadd: Test adding and removing of groups with maximal valid name and name ending with $ """ - (status, output) = commands.getstatusoutput("groupadd aaaaabbbbbcccccdddddeeeeefffffgg") #32 chars - self.assertEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupadd aaaaabbbbbcccccdddddeeeeefffffg\$") #32 chars - self.assertEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupdel aaaaabbbbbcccccdddddeeeeefffffgg") #32 chars - self.assertEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupdel aaaaabbbbbcccccdddddeeeeefffffg\$") #32 chars - self.assertEqual(status, 0, output) - - -class TestGroupmod(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.groupname = "test-shadow-utils-groups" - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - def tearDown(self): - commands.getstatusoutput("groupdel %s" % (self.groupname)) - - def testChangeGID(self): - """ groupmod: Test changing a gid of a group """ - expected = GroupInfo() - expected["gr_name"] = self.groupname - expected["gr_gid"] = 54321 - - (status, output) = commands.getstatusoutput("groupmod -g%d %s" % (expected["gr_gid"], self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not change GID of an existing group") - - def testChangeGIDToExistingValue(self): - """ groupmod: Test changing GID to an existing value """ - second_name = "%s-2" % (self.groupname) - - created = GroupInfo() - created.get_info_name(self.groupname) - - expected = GroupInfo() - expected["gr_name"] = self.groupname - expected["gr_gid"] = created["gr_gid"] - - (status, output) = commands.getstatusoutput("groupadd %s" % (second_name)) - self.failUnlessEqual(status, 0, output) - - # try to assingn GID of the first group to the second - this should fail without the -o option - (status, output) = commands.getstatusoutput("groupmod -g%d %s" % (created["gr_gid"], second_name)) - self.failIfEqual(status, 0, output) - - # should pass with the -o option - (status, output) = commands.getstatusoutput("groupmod -g%d -o %s" % (created["gr_gid"], second_name)) - self.failUnlessEqual(status, 0, output) - - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not change GID of an existing group to an existing one") - - # clean up - commands.getstatusoutput("groupdel %s" % (second_name)) - self.failUnlessEqual(status, 0, output) - - def testChangeGroupName(self): - """ groupmod: Test changing a group's name """ - second_name = "%s-2" % (self.groupname) - - created = GroupInfo() - created.get_info_name(self.groupname) - - (status, output) = commands.getstatusoutput("groupmod -n%s %s" % (second_name, self.groupname)) - self.failUnlessEqual(status, 0, output) - - changed = GroupInfo() - changed.get_info_gid(created["gr_gid"]) - self.assertEqual(changed["gr_name"], second_name) - self.assertEqual(changed["gr_gid"], created["gr_gid"]) - - # change back, so the group could be deleted by tearDown - (status, output) = commands.getstatusoutput("groupmod -n%s %s" % (self.groupname, second_name)) - self.failUnlessEqual(status, 0, output) - - def testChangeGroupNameExisting(self): - """ groupmod: Test changing a group's name to an existing one """ - existing = "bin" - (status, output) = commands.getstatusoutput("groupmod -n%s %s" % (existing, self.groupname)) - self.assertNotEqual(status, 0, output) # man groupmod -> 9: group name already in use - - def testChangeNonExistingGroup(self): - """ groupmod: Test properties of a non-existing group """ - nonexistent = "foobar" - (status, output) = commands.getstatusoutput("groupmod -nspameggs %s" % (nonexistent)) - self.assertNotEqual(status, 0, status) # man groupmod -> 6: specified group doesn't exist - -class TestGroupdel(unittest.TestCase, ShadowUtilsTestBase): - def testCorrectGroupdel(self): - """ groupdel: Basic usage of groupdel """ - self.groupname = "test-shadow-utils-groups" - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupdel %s" % (self.groupname)) - self.assertEqual(status, 0, output) - - def testGroupdelNoSuchGroup(self): - """ groupdel: Remove non-existing group """ - (status, output) = commands.getstatusoutput("groupdel foobar") - self.assertNotEqual(status, 0, output) - - def testRemovePrimaryGroup(self): - """ groupdel: Remove a primary group of an user """ - username = "test-groupdel-primary" - (status, output) = commands.getstatusoutput("useradd %s" % (username)) - self.failUnlessEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("groupdel %s" % (username)) - self.assertNotEqual(status, 0, output) - - # clean up - (status, output) = commands.getstatusoutput("userdel -r %s" % (username)) - self.failUnlessEqual(status, 0, output) - -class TestPwckGrpck(unittest.TestCase): - def setUp(self): - self.passwd_path = tempfile.mktemp(suffix="test-pwck-passwd") - self.passwd_file = open(self.passwd_path, "w") - self.group_path = tempfile.mktemp(suffix="test-pwck-grp") - self.group_file = open(self.group_path, "w") - self.gshadow_path = tempfile.mktemp(suffix="test-pwck-gshadow") - self.gshadow_file = open(self.gshadow_path, "w") - - def tearDown(self): - self.passwd_file.close() - self.group_file.close() - self.gshadow_file.close() - - os.remove(self.passwd_path) - os.remove(self.group_path) - os.remove(self.gshadow_path) - - def runPwckCheck(self, passwd, group): - self.passwd_file.truncate() - self.group_file.truncate() - - self.passwd_file.write(passwd) - self.passwd_file.flush() - self.group_file.write(group) - self.group_file.flush() - - command = "pwck -r %s %s" % (self.passwd_path, self.group_path) - return commands.getstatusoutput(command) - - def runGrpCheck(self, group, gshadow): - self.group_file.truncate() - self.gshadow_file.truncate() - - self.gshadow_file.write(gshadow) - self.gshadow_file.flush() - - self.group_file.write(group) - self.group_file.flush() - - command = "grpck -r %s %s" % (self.group_path, self.gshadow_path) - return commands.getstatusoutput(command) - - - def testValidEntries(self): - """ pwck: a valid entry """ - status, output = self.runPwckCheck("foo:x:685:0::/dev/null:/bin/bash", "") - rhv = RedHatVersion() - runs = rhv.get_info() - if rhv.is_rhel(): - if runs[1] < 6: - self.assertEqual(status, 0, output) - else: - self.assertNotEqual(status, 0, output) - - def testNumberOfFields(self): - """ pwck: invalid number of fields in the record """ - not_enough = "foo:x:685:685::/dev/null" - too_many = "foo:x:685:685::/dev/null:/bin/bash:comment" - status, output = self.runPwckCheck(not_enough, "") - self.assertNotEqual(status, 0, output) - - status, output = self.runPwckCheck(too_many, "") - self.assertNotEqual(status, 0, output) - - def testUniqueUserName(self): - """ pwck: unique user name in the record """ - duplicate_username = "foo:x:685:685::/dev/null:/bin/bash\nfoo:x:686:686::/dev/null:/bin/bash" - status, output = self.runPwckCheck(duplicate_username, "") - self.assertNotEqual(status, 0, output) - - def testValidID(self): - """ pwck: invalid UID in the records """ - invalid_ids = [ "foo:x:-1:685::/dev/null:/bin/bash", "foo:x:blah:685::/dev/null:/bin/bash", "foo:x:1234567890:685::/dev/null:/bin/bash" ] - for record in invalid_ids: - status, output = self.runPwckCheck(record, "") - self.assertNotEqual(status, 0, record) - - - def testValidPrimaryGroup(self): - """ pwck: invalid primary group """ - invalid_groups = [ "foo:x:685:-1::/dev/null:/bin/bash", "foo:x:685:blah::/dev/null:/bin/bash", "foo:x:685:1234567890::/dev/null:/bin/bash" ] - for record in invalid_groups: - status, output = self.runPwckCheck("", record) - self.assertNotEqual(status, 0, output) - - def testValidHomeDir(self): - """ pwck: invalid home dir """ - for record in [ "foo:x:685:685::123:/bin/bash", "foo:x:685:685::/path/to/nowhere:/bin/bash", "foo:x:685:1234567890::!:/bin/bash" ]: - status, output = self.runPwckCheck(record, "") - self.assertNotEqual(status, 0, output) - - def testBZ164954(self): - """ grpck: regression test for BZ164954 """ - record = "root:x:0:root\nbin:x:1:root,bin,daemon\ndaemon:x:2:root,bin,daemon\nsys:x:3:root,bin,adm\nadm:x:4:root,adm,daemon" - status, output = self.runGrpCheck("", record) - self.assertNotEqual(status, 0, output) - -if __name__ == "__main__": - broken_on_rhel4 = { "TestUseradd" : [ "testCustomUID", "testCustomGID" ] } - - if os.getuid() != 0: - print "This test must be run as root" - sys.exit(1) - - unittest.main() - diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 09f4769..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -# This first play always runs on the local staging system -- hosts: localhost - roles: - - role: standard-test-beakerlib - tags: - - classic - - atomic - tests: - - sanity - required_packages: - - shadow-utils # sanity test needs shadow-utils - - python # sanity test needs python