From e1ce821d4521d7ede777a6cd51f4cbcfeb1b5d9a Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 17 Oct 2014 17:03:29 +0200 Subject: [PATCH] update auditing to cover more events and fix some incorrect audit records (auditing patch by Steve Grubb (#1151580)) - apply the same new allocation algorithm to uids as for gids --- shadow-4.1.5.1-audit-update.patch | 2250 +++++++++++++++++ ...loc.patch => shadow-4.1.5.1-id-alloc.patch | 625 ++++- shadow-utils.spec | 13 +- 3 files changed, 2861 insertions(+), 27 deletions(-) create mode 100644 shadow-4.1.5.1-audit-update.patch rename shadow-4.1.5.1-group-alloc.patch => shadow-4.1.5.1-id-alloc.patch (52%) diff --git a/shadow-4.1.5.1-audit-update.patch b/shadow-4.1.5.1-audit-update.patch new file mode 100644 index 0000000..c25db61 --- /dev/null +++ b/shadow-4.1.5.1-audit-update.patch @@ -0,0 +1,2250 @@ +diff -urp shadow-4.1.5.1.orig/lib/prototypes.h shadow-4.1.5.1/lib/prototypes.h +--- shadow-4.1.5.1.orig/lib/prototypes.h 2014-09-13 15:45:54.953829562 -0400 ++++ shadow-4.1.5.1/lib/prototypes.h 2014-10-14 08:39:23.785884075 -0400 +@@ -195,12 +195,21 @@ extern int audit_fd; + extern void audit_help_open (void); + /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ + #define AUDIT_NO_ID ((unsigned int) -1) ++#ifndef AUDIT_GRP_MGMT ++#define AUDIT_GRP_MGMT 1132 /* Group account was modified */ ++#endif ++#ifndef AUDIT_GRP_CHAUTHTOK ++#define AUDIT_GRP_CHAUTHTOK 1133 /* Group account password was changed */ ++#endif + typedef enum { + SHADOW_AUDIT_FAILURE = 0, + SHADOW_AUDIT_SUCCESS = 1} shadow_audit_result; + extern void audit_logger (int type, const char *pgname, const char *op, + const char *name, unsigned int id, + shadow_audit_result result); ++void audit_logger_with_group (int type, unused const char *pgname, ++ const char *op, const char *name, unsigned int id, ++ const char *grp, shadow_audit_result result); + void audit_logger_message (const char *message, shadow_audit_result result); + #endif + +diff -urp shadow-4.1.5.1.orig/libmisc/audit_help.c shadow-4.1.5.1/libmisc/audit_help.c +--- shadow-4.1.5.1.orig/libmisc/audit_help.c 2010-08-21 07:41:28.000000000 -0400 ++++ shadow-4.1.5.1/libmisc/audit_help.c 2014-10-14 08:39:23.785884075 -0400 +@@ -68,7 +68,7 @@ void audit_help_open (void) + * This function will log a message to the audit system using a predefined + * message format. Parameter usage is as follows: + * +- * type - type of message: AUDIT_USER_CHAUTHTOK for changing any account ++ * type - type of message: AUDIT_USER_MGMT for changing any account + * attributes. + * pgname - program's name + * op - operation. "adding user", "changing finger info", "deleting group" +@@ -88,6 +88,39 @@ void audit_logger (int type, unused cons + } + } + ++/* ++ * This function will log a message to the audit system using a predefined ++ * message format. Parameter usage is as follows: ++ * ++ * type - type of message: AUDIT_USER_MGMT for changing any account ++ * attributes. ++ * pgname - program's name ++ * op - operation. "adding user", "changing finger info", "deleting group" ++ * name - user's account or group name. If not available use NULL. ++ * id - uid or gid that the operation is being performed on. This is used ++ * only when user is NULL. ++ * grp - group name associated with event ++ */ ++void audit_logger_with_group (int type, unused const char *pgname, ++ const char *op, const char *name, unsigned int id, ++ const char *grp, shadow_audit_result result) ++{ ++ int len; ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1], buf[1024]; ++ if (audit_fd < 0) { ++ return; ++ } ++ len = strnlen(grp, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(grp, len)) { ++ snprintf(buf, sizeof(buf), "%s grp=%s", op, ++ audit_encode_value(enc_group, grp, len)); ++ } else { ++ snprintf(buf, sizeof(buf), "%s grp=\"%s\"", op, grp); ++ } ++ audit_log_acct_message (audit_fd, type, NULL, buf, name, id, ++ NULL, NULL, NULL, (int) result); ++} ++ + void audit_logger_message (const char *message, shadow_audit_result result) + { + if (audit_fd < 0) { +diff -urp shadow-4.1.5.1.orig/libmisc/cleanup_group.c shadow-4.1.5.1/libmisc/cleanup_group.c +--- shadow-4.1.5.1.orig/libmisc/cleanup_group.c 2008-12-23 17:45:18.000000000 -0500 ++++ shadow-4.1.5.1/libmisc/cleanup_group.c 2014-10-14 09:00:33.594753105 -0400 +@@ -83,7 +83,7 @@ void cleanup_report_mod_group (void *cle + gr_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -101,7 +101,7 @@ void cleanup_report_mod_gshadow (void *c + sgr_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -122,7 +122,7 @@ void cleanup_report_add_group_group (voi + SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/group", ++ "adding-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -141,8 +141,8 @@ void cleanup_report_add_group_gshadow (v + + SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "adding-shadow-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -164,8 +164,8 @@ void cleanup_report_del_group_group (voi + "failed to remove group %s from %s", + name, gr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "removing group from /etc/group", ++ audit_logger (AUDIT_DEL_GROUP, Prog, ++ "removing-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -187,8 +187,8 @@ void cleanup_report_del_group_gshadow (v + "failed to remove group %s from %s", + name, sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "removing group from /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "removing-shadow-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -208,7 +208,7 @@ void cleanup_unlock_group (unused void * + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking group file", ++ audit_logger_message ("unlocking-group", + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -228,7 +228,7 @@ void cleanup_unlock_gshadow (unused void + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking gshadow file", ++ audit_logger_message ("unlocking-gshadow", + SHADOW_AUDIT_FAILURE); + #endif + } +diff -urp shadow-4.1.5.1.orig/libmisc/cleanup_user.c shadow-4.1.5.1/libmisc/cleanup_user.c +--- shadow-4.1.5.1.orig/libmisc/cleanup_user.c 2008-12-23 17:45:18.000000000 -0500 ++++ shadow-4.1.5.1/libmisc/cleanup_user.c 2014-10-14 09:01:51.878745031 -0400 +@@ -65,7 +65,7 @@ void cleanup_report_mod_passwd (void *cl + pw_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_USER_MGMT, Prog, + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -86,7 +86,7 @@ void cleanup_report_add_user_passwd (voi + SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to /etc/passwd", ++ "adding-user", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -105,8 +105,8 @@ void cleanup_report_add_user_shadow (voi + + SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to /etc/shadow", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "adding-shadow-user", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -125,7 +125,7 @@ void cleanup_unlock_passwd (unused void + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking passwd file", ++ audit_logger_message ("unlocking-passwd", + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -144,7 +144,7 @@ void cleanup_unlock_shadow (unused void + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger_message ("unlocking shadow file", ++ audit_logger_message ("unlocking-shadow", + SHADOW_AUDIT_FAILURE); + #endif + } +diff -urp shadow-4.1.5.1.orig/src/chage.c shadow-4.1.5.1/src/chage.c +--- shadow-4.1.5.1.orig/src/chage.c 2011-11-19 17:54:47.000000000 -0500 ++++ shadow-4.1.5.1/src/chage.c 2014-10-14 08:39:23.787884075 -0400 +@@ -126,9 +126,10 @@ static /*@noreturn@*/void fail_exit (int + + #ifdef WITH_AUDIT + if (E_SUCCESS != code) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change age", +- user_name, (unsigned int) user_uid, 0); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-age", ++ user_name, (unsigned int) user_uid, ++ SHADOW_AUDIT_FAILURE); + } + #endif + +@@ -873,11 +874,7 @@ int main (int argc, char **argv) + fprintf (stderr, _("%s: Permission denied.\n"), Prog); + fail_exit (E_NOPERM); + } +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "display aging info", +- user_name, (unsigned int) user_uid, 1); +-#endif ++ /* Displaying fields is not of interest to audit */ + list_fields (); + fail_exit (E_SUCCESS); + } +@@ -896,41 +893,43 @@ int main (int argc, char **argv) + } + #ifdef WITH_AUDIT + else { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change all aging information", +- user_name, (unsigned int) user_uid, 1); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-all-aging-information", ++ user_name, (unsigned int) user_uid, ++ SHADOW_AUDIT_SUCCESS); + } + #endif + } else { + #ifdef WITH_AUDIT + if (Mflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change max age", +- user_name, (unsigned int) user_uid, 1); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-max-age", ++ user_name, (unsigned int) user_uid, ++ SHADOW_AUDIT_SUCCESS); + } + if (mflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change min age", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-min-age", + user_name, (unsigned int) user_uid, 1); + } + if (dflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change last change date", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-last-change-date", + user_name, (unsigned int) user_uid, 1); + } + if (Wflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change passwd warning", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-passwd-warning", + user_name, (unsigned int) user_uid, 1); + } + if (Iflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change inactive days", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-inactive-days", + user_name, (unsigned int) user_uid, 1); + } + if (Eflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "change passwd expiration", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "change-passwd-expiration", + user_name, (unsigned int) user_uid, 1); + } + #endif +diff -urp shadow-4.1.5.1.orig/src/gpasswd.c shadow-4.1.5.1/src/gpasswd.c +--- shadow-4.1.5.1.orig/src/gpasswd.c 2014-09-13 15:45:54.989829559 -0400 ++++ shadow-4.1.5.1/src/gpasswd.c 2014-10-14 08:43:07.393861012 -0400 +@@ -137,7 +137,7 @@ static void usage (int status) + (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); + (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); + (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); +- (void) fputs (_(" -r, --remove-password remove the GROUP's password\n"), usageout); ++ (void) fputs (_(" -r, --delete-password remove the GROUP's password\n"), usageout); + (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); + (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); + #ifdef SHADOWGRP +@@ -397,21 +397,14 @@ static void open_files (void) + + static void log_gpasswd_failure (const char *suffix) + { +-#ifdef WITH_AUDIT +- char buf[1024]; +-#endif + if (aflg) { + SYSLOG ((LOG_ERR, + "%s failed to add user %s to group %s%s", + myname, user, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to add user %s to group %s%s", +- myname, user, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (dflg) { +@@ -419,13 +412,9 @@ static void log_gpasswd_failure (const c + "%s failed to remove user %s from group %s%s", + myname, user, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to remove user %s from group %s%s", +- myname, user, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (rflg) { +@@ -433,13 +422,9 @@ static void log_gpasswd_failure (const c + "%s failed to remove password of group %s%s", + myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to remove password of group %s%s", +- myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "delete-group-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (Rflg) { +@@ -447,13 +432,9 @@ static void log_gpasswd_failure (const c + "%s failed to restrict access to group %s%s", + myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to restrict access to group %s%s", +- myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "restrict-group", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } else if (Aflg || Mflg) { +@@ -463,13 +444,9 @@ static void log_gpasswd_failure (const c + "%s failed to set the administrators of group %s to %s%s", + myname, group, admins, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to set the administrators of group %s to %s%s", +- myname, group, admins, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "set-admins-of-group", ++ admins, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -479,13 +456,9 @@ static void log_gpasswd_failure (const c + "%s failed to set the members of group %s to %s%s", + myname, group, members, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to set the members of group %s to %s%s", +- myname, group, members, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-users-to-group", ++ members, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -494,13 +467,9 @@ static void log_gpasswd_failure (const c + "%s failed to change password of group %s%s", + myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "%s failed to change password of group %s%s", +- myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "change-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_FAILURE); + #endif + } +@@ -531,21 +500,14 @@ static void log_gpasswd_failure_gshadow + + static void log_gpasswd_success (const char *suffix) + { +-#ifdef WITH_AUDIT +- char buf[1024]; +-#endif + if (aflg) { + SYSLOG ((LOG_INFO, + "user %s added by %s to group %s%s", + user, myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "user %s added by %s to group %s%s", +- user, myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (dflg) { +@@ -553,13 +515,9 @@ static void log_gpasswd_success (const c + "user %s removed by %s from group %s%s", + user, myname, group, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "user %s removed by %s from group %s%s", +- user, myname, group, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (rflg) { +@@ -567,13 +525,9 @@ static void log_gpasswd_success (const c + "password of group %s removed by %s%s", + group, myname, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "password of group %s removed by %s%s", +- group, myname, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "delete-group-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (Rflg) { +@@ -581,13 +535,9 @@ static void log_gpasswd_success (const c + "access to group %s restricted by %s%s", + group, myname, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "access to group %s restricted by %s%s", +- group, myname, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "restrict-group", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } else if (Aflg || Mflg) { +@@ -597,13 +547,9 @@ static void log_gpasswd_success (const c + "administrators of group %s set by %s to %s%s", + group, myname, admins, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "administrators of group %s set by %s to %s%s", +- group, myname, admins, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "set-admins-of-group", ++ admins, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } +@@ -613,13 +559,9 @@ static void log_gpasswd_success (const c + "members of group %s set by %s to %s%s", + group, myname, members, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "members of group %s set by %s to %s%s", +- group, myname, members, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_ACCT, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-users-to-group", ++ members, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } +@@ -628,13 +570,9 @@ static void log_gpasswd_success (const c + "password of group %s changed by %s%s", + group, myname, suffix)); + #ifdef WITH_AUDIT +- snprintf (buf, 1023, +- "password of group %s changed by %s%s", +- group, myname, suffix); +- buf[1023] = '\0'; +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- buf, +- group, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, ++ "change-password", ++ myname, AUDIT_NO_ID, group, + SHADOW_AUDIT_SUCCESS); + #endif + } +diff -urp shadow-4.1.5.1.orig/src/groupadd.c shadow-4.1.5.1/src/groupadd.c +--- shadow-4.1.5.1.orig/src/groupadd.c 2011-11-18 16:23:30.000000000 -0500 ++++ shadow-4.1.5.1/src/groupadd.c 2014-10-14 08:39:23.800884073 -0400 +@@ -127,6 +127,15 @@ static /*@noreturn@*/void usage (int sta + exit (status); + } + ++static void fail_exit(int status) ++{ ++#ifdef WITH_AUDIT ++ audit_logger(AUDIT_ADD_GROUP, Prog, "add-group", group_name, ++ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); ++#endif ++ exit (status); ++} ++ + /* + * new_grent - initialize the values in a group file entry + * +@@ -210,7 +219,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), grp.gr_name); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef SHADOWGRP + /* +@@ -220,7 +229,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), sgrp.sg_name); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #endif /* SHADOWGRP */ + } +@@ -244,7 +253,7 @@ static void check_new_name (void) + fprintf (stderr, _("%s: '%s' is not a valid group name\n"), + Prog, group_name); + +- exit (E_BAD_ARG); ++ fail_exit (E_BAD_ARG); + } + + /* +@@ -260,11 +269,11 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/group", ++ "add-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -282,11 +291,11 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group to /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "add-shadow-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -300,12 +309,6 @@ static void close_files (void) + #endif /* SHADOWGRP */ + + /* Report success at the system level */ +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, +- "", +- group_name, (unsigned int) group_id, +- SHADOW_AUDIT_SUCCESS); +-#endif + SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", + group_name, (unsigned int) group_id)); + del_cleanup (cleanup_report_add_group); +@@ -323,7 +326,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_group, NULL); + +@@ -333,7 +336,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_gshadow, NULL); + } +@@ -349,7 +352,7 @@ static void open_files (void) + if (gr_open (O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef SHADOWGRP +@@ -359,7 +362,7 @@ static void open_files (void) + _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + } + #endif /* SHADOWGRP */ +@@ -489,7 +492,7 @@ static void check_flags (void) + fprintf (stderr, + _("%s: group '%s' already exists\n"), + Prog, group_name); +- exit (E_NAME_IN_USE); ++ fail_exit (E_NAME_IN_USE); + } + + if (gflg && (getgrgid (group_id) != NULL)) { +@@ -508,7 +511,7 @@ static void check_flags (void) + fprintf (stderr, + _("%s: GID '%lu' already exists\n"), + Prog, (unsigned long int) group_id); +- exit (E_GID_IN_USE); ++ fail_exit (E_GID_IN_USE); + } + } + } +@@ -536,7 +539,7 @@ static void check_perms (void) + fprintf (stderr, + _("%s: Cannot determine your user name.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); +@@ -556,7 +559,7 @@ static void check_perms (void) + if (NULL != pamh) { + (void) pam_end (pamh, retval); + } +- exit (1); ++ fail_exit (1); + } + (void) pam_end (pamh, retval); + #endif /* USE_PAM */ +@@ -588,7 +591,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot setup cleanup service.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + /* +@@ -610,7 +613,7 @@ int main (int argc, char **argv) + + if (!gflg) { + if (find_new_gid (rflg, &group_id, NULL) < 0) { +- exit (E_GID_IN_USE); ++ fail_exit (E_GID_IN_USE); + } + } + +diff -urp shadow-4.1.5.1.orig/src/groupdel.c shadow-4.1.5.1/src/groupdel.c +--- shadow-4.1.5.1.orig/src/groupdel.c 2011-11-18 16:23:30.000000000 -0500 ++++ shadow-4.1.5.1/src/groupdel.c 2014-10-14 08:39:23.801884073 -0400 +@@ -100,6 +100,15 @@ static /*@noreturn@*/void usage (int sta + exit (status); + } + ++static void fail_exit(int status) ++{ ++#ifdef WITH_AUDIT ++ audit_logger(AUDIT_GRP_MGMT, Prog, "delete-group", group_name, ++ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); ++#endif ++ exit (status); ++} ++ + /* + * grp_update - update group file entries + * +@@ -126,7 +135,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, group_name, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef SHADOWGRP +@@ -138,7 +147,7 @@ static void grp_update (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, group_name, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + } + #endif /* SHADOWGRP */ +@@ -157,12 +166,12 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_GROUP, Prog, +- "removing group from /etc/group", ++ "delete-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -182,12 +191,12 @@ static void close_files (void) + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "removing group from /etc/gshadow", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "delete-shadow-group", + group_name, (unsigned int) group_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -201,13 +210,6 @@ static void close_files (void) + } + #endif /* SHADOWGRP */ + +- /* Report success at the system level */ +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "", +- group_name, (unsigned int) group_id, +- SHADOW_AUDIT_SUCCESS); +-#endif + SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); + del_cleanup (cleanup_report_del_group); + } +@@ -224,7 +226,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_group, NULL); + #ifdef SHADOWGRP +@@ -233,7 +235,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + add_cleanup (cleanup_unlock_gshadow, NULL); + } +@@ -251,7 +253,7 @@ static void open_files (void) + _("%s: cannot open %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + #ifdef SHADOWGRP + if (is_shadow_grp) { +@@ -260,7 +262,7 @@ static void open_files (void) + _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); +- exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE); + } + } + #endif /* SHADOWGRP */ +@@ -301,7 +303,7 @@ static void group_busy (gid_t gid) + fprintf (stderr, + _("%s: cannot remove the primary group of user '%s'\n"), + Prog, pwd->pw_name); +- exit (E_GROUP_BUSY); ++ fail_exit (E_GROUP_BUSY); + } + + /* +@@ -379,7 +381,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot setup cleanup service.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + process_flags (argc, argv); +@@ -393,7 +395,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot determine your user name.\n"), + Prog); +- exit (1); ++ fail_exit (1); + } + + retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh); +@@ -414,7 +416,7 @@ int main (int argc, char **argv) + if (NULL != pamh) { + (void) pam_end (pamh, retval); + } +- exit (1); ++ fail_exit (1); + } + (void) pam_end (pamh, retval); + #endif /* USE_PAM */ +@@ -434,7 +436,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: group '%s' does not exist\n"), + Prog, group_name); +- exit (E_NOTFOUND); ++ fail_exit (E_NOTFOUND); + } + + group_id = grp->gr_gid; +@@ -458,7 +460,7 @@ int main (int argc, char **argv) + _("%s: %s is the NIS master\n"), + Prog, nis_master); + } +- exit (E_NOTFOUND); ++ fail_exit (E_NOTFOUND); + } + #endif + +diff -urp shadow-4.1.5.1.orig/src/groupmod.c shadow-4.1.5.1/src/groupmod.c +--- shadow-4.1.5.1.orig/src/groupmod.c 2011-11-18 16:23:30.000000000 -0500 ++++ shadow-4.1.5.1/src/groupmod.c 2014-10-14 08:49:28.517821702 -0400 +@@ -438,7 +438,7 @@ static void close_files (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info_group.audit_msg, + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); +@@ -461,7 +461,7 @@ static void close_files (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info_gshadow.audit_msg, + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); +@@ -484,7 +484,7 @@ static void close_files (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, Prog, + info_passwd.audit_msg, + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); +@@ -499,8 +499,8 @@ static void close_files (void) + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_ACCT, Prog, +- "modifying group", ++ audit_logger (AUDIT_GRP_MGMT, Prog, ++ "modify-group", + group_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -512,6 +512,8 @@ static void close_files (void) + */ + static void prepare_failure_reports (void) + { ++ char *nv_pair, nv[64]; ++ + info_group.name = group_name; + #ifdef SHADOWGRP + info_gshadow.name = group_name; +@@ -524,76 +526,106 @@ static void prepare_failure_reports (voi + #endif + info_passwd.audit_msg = xmalloc (512); + +- (void) snprintf (info_group.audit_msg, 511, +- "changing %s; ", gr_dbname ()); ++ info_group.action = xmalloc (512); + #ifdef SHADOWGRP +- (void) snprintf (info_gshadow.audit_msg, 511, +- "changing %s; ", sgr_dbname ()); ++ info_gshadow.action = xmalloc (512); + #endif +- (void) snprintf (info_passwd.audit_msg, 511, +- "changing %s; ", pw_dbname ()); ++ info_passwd.action = xmalloc (512); + +- info_group.action = info_group.audit_msg +- + strlen (info_group.audit_msg); ++ (void) snprintf (info_group.audit_msg, 511, ++ "changing-group"); + #ifdef SHADOWGRP +- info_gshadow.action = info_gshadow.audit_msg +- + strlen (info_gshadow.audit_msg); ++ (void) snprintf (info_gshadow.audit_msg, 511, ++ "changing-shadow-group"); + #endif +- info_passwd.action = info_passwd.audit_msg +- + strlen (info_passwd.audit_msg); ++ (void) snprintf (info_passwd.audit_msg, 511, ++ "changing-group-passwd"); + ++ nv_pair = audit_encode_nv_string(" grp", group_name, ++ strlen(group_name)); ++ if(nv_pair) { ++ strncat(info_group.audit_msg, nv_pair, ++ 511 - strlen(info_group.audit_msg)); ++#ifdef SHADOWGRP ++ strncat(info_gshadow.audit_msg, nv_pair, ++ 511 - strlen(info_gshadow.audit_msg)); ++#endif ++ strncat(info_passwd.audit_msg, nv_pair, ++ 511 - strlen(info_passwd.audit_msg)); ++ free(nv_pair); ++ } ++ snprintf(nv, sizeof(nv), " gid=%lu", group_id); ++ strncat(info_group.audit_msg, nv, 511 - strlen(info_group.audit_msg)); ++ strncat(info_passwd.audit_msg, nv, 511 - strlen(info_passwd.audit_msg)); ++ + (void) snprintf (info_group.action, +- 511 - strlen (info_group.audit_msg), ++ 511, + "group %s/%lu", + group_name, (unsigned long int) group_id); + #ifdef SHADOWGRP + (void) snprintf (info_gshadow.action, +- 511 - strlen (info_group.audit_msg), ++ 511, + "group %s", group_name); + #endif + (void) snprintf (info_passwd.action, +- 511 - strlen (info_group.audit_msg), ++ 511, + "group %s/%lu", + group_name, (unsigned long int) group_id); + + if (nflg) { ++ nv_pair = audit_encode_nv_string(" new_group", group_newname, ++ strlen(group_newname)); ++ strncat(info_group.audit_msg, nv_pair, ++ 511 - strlen(info_group.audit_msg)); + strncat (info_group.action, ", new name: ", +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + strncat (info_group.action, group_newname, +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + + #ifdef SHADOWGRP ++ strncat(info_gshadow.audit_msg, nv_pair, ++ 511 - strlen(info_gshadow.audit_msg)); + strncat (info_gshadow.action, ", new name: ", +- 511 - strlen (info_gshadow.audit_msg)); ++ 511 - strlen (info_gshadow.action)); + strncat (info_gshadow.action, group_newname, +- 511 - strlen (info_gshadow.audit_msg)); ++ 511 - strlen (info_gshadow.action)); + #endif + ++ strncat(info_passwd.audit_msg, nv_pair, ++ 511 - strlen(info_passwd.audit_msg)); + strncat (info_passwd.action, ", new name: ", +- 511 - strlen (info_passwd.audit_msg)); ++ 511 - strlen (info_passwd.action)); + strncat (info_passwd.action, group_newname, +- 511 - strlen (info_passwd.audit_msg)); ++ 511 - strlen (info_passwd.action)); ++ free(nv_pair); + } + if (pflg) { ++ /* Note: audit doesn't want this value recorded */ + strncat (info_group.action, ", new password", +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + + #ifdef SHADOWGRP + strncat (info_gshadow.action, ", new password", +- 511 - strlen (info_gshadow.audit_msg)); ++ 511 - strlen (info_gshadow.action)); + #endif + } + if (gflg) { ++ snprintf(nv, sizeof(nv), " new_gid=%lu", group_newid); ++ strncat(info_group.audit_msg, nv, ++ 511 - strlen(info_group.audit_msg)); ++ strncat(info_passwd.audit_msg, nv, ++ 511 - strlen(info_passwd.audit_msg)); ++ + strncat (info_group.action, ", new gid: ", +- 511 - strlen (info_group.audit_msg)); ++ 511 - strlen (info_group.action)); + (void) snprintf (info_group.action+strlen (info_group.action), +- 511 - strlen (info_group.audit_msg), ++ 511 - strlen (info_group.action), + "%lu", (unsigned long int) group_newid); + + strncat (info_passwd.action, ", new gid: ", +- 511 - strlen (info_passwd.audit_msg)); ++ 511 - strlen (info_passwd.action)); + (void) snprintf (info_passwd.action+strlen (info_passwd.action), +- 511 - strlen (info_passwd.audit_msg), ++ 511 - strlen (info_passwd.action), + "%lu", (unsigned long int) group_newid); + } + info_group.audit_msg[511] = '\0'; +@@ -601,6 +633,11 @@ static void prepare_failure_reports (voi + info_gshadow.audit_msg[511] = '\0'; + #endif + info_passwd.audit_msg[511] = '\0'; ++ info_group.action[511] = '\0'; ++#ifdef SHADOWGRP ++ info_gshadow.action[511] = '\0'; ++#endif ++ info_passwd.action[511] = '\0'; + + // FIXME: add a system cleanup + add_cleanup (cleanup_report_mod_group, &info_group); +diff -urp shadow-4.1.5.1.orig/src/newgrp.c shadow-4.1.5.1/src/newgrp.c +--- shadow-4.1.5.1.orig/src/newgrp.c 2014-09-13 15:45:55.010829557 -0400 ++++ shadow-4.1.5.1/src/newgrp.c 2014-10-14 08:39:23.802884073 -0400 +@@ -197,11 +197,12 @@ static void check_perms (const struct gr + strcmp (cpasswd, grp->gr_passwd) != 0) { + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "authentication new-gid=%lu", ++ "authentication new_gid=%lu", + (unsigned long) grp->gr_gid); + audit_logger (AUDIT_GRP_AUTH, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + #endif + SYSLOG ((LOG_INFO, + "Invalid password for group '%s' from '%s'", +@@ -212,11 +213,12 @@ static void check_perms (const struct gr + } + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "authentication new-gid=%lu", ++ "authentication new_gid=%lu", + (unsigned long) grp->gr_gid); + audit_logger (AUDIT_GRP_AUTH, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 1); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_SUCCESS); + #endif + } + +@@ -227,19 +229,6 @@ failure: + * harm. -- JWP + */ + closelog (); +-#ifdef WITH_AUDIT +- if (groupname) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", groupname); +- audit_logger (AUDIT_CHGRP_ID, Prog, +- audit_buf, NULL, +- (unsigned int) getuid (), 0); +- } else { +- audit_logger (AUDIT_CHGRP_ID, Prog, +- "changing", NULL, +- (unsigned int) getuid (), 0); +- } +-#endif + exit (EXIT_FAILURE); + } + +@@ -308,15 +297,27 @@ static void syslog_sg (const char *name, + is_newgrp ? "newgrp" : "sg", strerror (errno)); + #ifdef WITH_AUDIT + if (group) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", group); ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; ++ int len = strnlen(group, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(group, len)) { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=%s", ++ audit_encode_value(enc_group, ++ group, len)); ++ } else { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=\"%s\"", ++ group); ++ } + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } else { + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } + #endif + exit (EXIT_FAILURE); +@@ -442,7 +443,7 @@ int main (int argc, char **argv) + #ifdef WITH_AUDIT + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", + (unsigned long) getuid ())); +@@ -558,15 +559,26 @@ int main (int argc, char **argv) + perror ("getgroups"); + #ifdef WITH_AUDIT + if (group) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", group); ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; ++ int len = strnlen(group, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(group, len)) { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=%s", ++ audit_encode_value(enc_group, ++ group, len)); ++ } else { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=\"%s\"", group); ++ } + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } else { + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), ++ SHADOW_AUDIT_FAILURE); + } + #endif + exit (EXIT_FAILURE); +@@ -707,10 +719,10 @@ int main (int argc, char **argv) + perror ("setgid"); + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "changing new-gid=%lu", (unsigned long) gid); ++ "changing new_gid=%lu", (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + exit (EXIT_FAILURE); + } +@@ -719,10 +731,10 @@ int main (int argc, char **argv) + perror ("setuid"); + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "changing new-gid=%lu", (unsigned long) gid); ++ "changing new_gid=%lu", (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + exit (EXIT_FAILURE); + } +@@ -736,10 +748,10 @@ int main (int argc, char **argv) + execl (SHELL, "sh", "-c", command, (char *) 0); + #ifdef WITH_AUDIT + snprintf (audit_buf, sizeof(audit_buf), +- "changing new-gid=%lu", (unsigned long) gid); ++ "changing new_gid=%lu", (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + #endif + perror (SHELL); + exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); +@@ -803,11 +815,11 @@ int main (int argc, char **argv) + } + + #ifdef WITH_AUDIT +- snprintf (audit_buf, sizeof(audit_buf), "changing new-gid=%lu", ++ snprintf (audit_buf, sizeof(audit_buf), "changing new_gid=%lu", + (unsigned long) gid); + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 1); ++ (unsigned int) getuid (), SHADOW_AUDIT_SUCCESS); + #endif + /* + * Exec the login shell and go away. We are trying to get back to +@@ -831,15 +843,24 @@ int main (int argc, char **argv) + closelog (); + #ifdef WITH_AUDIT + if (NULL != group) { +- snprintf (audit_buf, sizeof(audit_buf), +- "changing new-group=%s", group); ++ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; ++ int len = strnlen(group, sizeof(enc_group)/2); ++ if (audit_value_needs_encoding(group, len)) { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=%s", ++ audit_encode_value(enc_group, ++ group, len)); ++ } else { ++ snprintf (audit_buf, sizeof(audit_buf), ++ "changing new_group=\"%s\"", group); ++ } + audit_logger (AUDIT_CHGRP_ID, Prog, + audit_buf, NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + } else { + audit_logger (AUDIT_CHGRP_ID, Prog, + "changing", NULL, +- (unsigned int) getuid (), 0); ++ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); + } + #endif + exit (EXIT_FAILURE); +diff -urp shadow-4.1.5.1.orig/src/useradd.c shadow-4.1.5.1/src/useradd.c +--- shadow-4.1.5.1.orig/src/useradd.c 2014-09-13 15:45:54.957829561 -0400 ++++ shadow-4.1.5.1/src/useradd.c 2014-10-14 08:52:53.066800605 -0400 +@@ -205,6 +205,8 @@ static void create_mail (void); + */ + static void fail_exit (int code) + { ++ int type; ++ + if (home_added) { + if (rmdir (user_home) != 0) { + fprintf (stderr, +@@ -218,12 +220,6 @@ static void fail_exit (int code) + if (spw_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking shadow file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -231,12 +227,6 @@ static void fail_exit (int code) + if (pw_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking passwd file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -244,12 +234,6 @@ static void fail_exit (int code) + if (gr_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking group file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } +@@ -258,20 +242,19 @@ static void fail_exit (int code) + if (sgr_unlock () == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking gshadow file", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + /* continue */ + } + } + #endif + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", ++ if (code == E_PW_UPDATE || code >= E_GRP_UPDATE) ++ type = AUDIT_USER_MGMT; ++ else ++ type = AUDIT_ADD_USER; ++ ++ audit_logger (type, Prog, ++ "add-user", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -578,7 +561,7 @@ static int set_defaults (void) + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USYS_CONFIG, Prog, +- "changing useradd defaults", ++ "changing-useradd-defaults", + NULL, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -848,12 +831,6 @@ static void grp_update (void) + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_GRP_UPDATE); /* XXX */ + } + +@@ -867,18 +844,12 @@ static void grp_update (void) + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), ngrp->gr_name); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user_name, AUDIT_NO_ID, ngrp->gr_name, + SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, +@@ -923,12 +894,6 @@ static void grp_update (void) + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to shadow group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_GRP_UPDATE); /* XXX */ + } + +@@ -942,18 +907,13 @@ static void grp_update (void) + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), nsgrp->sg_name); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to shadow group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif ++ + fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user to shadow group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-to-shadow-group", ++ user_name, AUDIT_NO_ID, nsgrp->sg_name, + SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, +@@ -1296,7 +1256,7 @@ static void process_flags (int argc, cha + Prog, user_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", ++ "add-user", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1385,7 +1345,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking shadow file", ++ "unlocking-shadow-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1398,7 +1358,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking passwd file", ++ "unlocking-passwd-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1410,7 +1370,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking group file", ++ "unlocking-group-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1424,7 +1384,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "unlocking gshadow file", ++ "unlocking-gshadow-file", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1584,7 +1544,7 @@ static void grp_add (void) + Prog, gr_dbname (), grp.gr_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group", ++ "add-group", + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1600,7 +1560,7 @@ static void grp_add (void) + Prog, sgr_dbname (), sgrp.sg_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group", ++ "add-group", + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +@@ -1610,7 +1570,7 @@ static void grp_add (void) + SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_GROUP, Prog, +- "adding group", ++ "add-group", + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -1725,17 +1685,11 @@ static void usr_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), spent.sp_namp); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding shadow password", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_PW_UPDATE); + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", ++ "add-user", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -1771,12 +1725,6 @@ static void create_home (void) + fprintf (stderr, + _("%s: cannot create directory %s\n"), + Prog, user_home); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding home directory", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_HOMEDIR); + } + chown (user_home, user_id, user_gid); +@@ -1784,8 +1732,8 @@ static void create_home (void) + 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK)); + home_added = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "add-home-dir", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + #endif +@@ -1951,12 +1899,6 @@ int main (int argc, char **argv) + */ + if (getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ + fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_NAME_IN_USE); + } + +@@ -1972,12 +1914,6 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), + Prog, user_name); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding group", +- user_name, AUDIT_NO_ID, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_NAME_IN_USE); + } + } +@@ -2007,12 +1943,6 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: UID %lu is not unique\n"), + Prog, (unsigned long) user_id); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding user", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif + fail_exit (E_UID_IN_USE); + } + } +@@ -2057,9 +1987,10 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), + Prog, user_name, user_selinux); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "adding SELinux user mapping", +- user_name, (unsigned int) user_id, 0); ++ audit_logger (AUDIT_ROLE_ASSIGN, Prog, ++ "add-selinux-user-mapping", ++ user_name, (unsigned int) user_id, ++ SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ + rv = E_SE_UPDATE; + } +diff -urp shadow-4.1.5.1.orig/src/userdel.c shadow-4.1.5.1/src/userdel.c +--- shadow-4.1.5.1.orig/src/userdel.c 2014-09-13 15:45:55.001829558 -0400 ++++ shadow-4.1.5.1/src/userdel.c 2014-10-14 08:44:52.714850149 -0400 +@@ -201,9 +201,9 @@ static void update_groups (void) + * Update the DBM group file with the new entry as well. + */ + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user from group", +- user_name, (unsigned int) user_id, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "deleting-user-from-group", ++ user_name, (unsigned int) user_id, ngrp->gr_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", +@@ -263,9 +263,9 @@ static void update_groups (void) + exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user from shadow group", +- user_name, (unsigned int) user_id, ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "deleting-user-from-shadow-group", ++ user_name, (unsigned int) user_id, nsgrp->sg_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", +@@ -342,9 +342,9 @@ static void remove_usergroup (void) + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "deleting group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_DEL_GROUP, Prog, ++ "delete-group", ++ user_name, AUDIT_NO_ID, user_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, +@@ -360,9 +360,9 @@ static void remove_usergroup (void) + fail_exit (E_GRP_UPDATE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, +- "deleting shadow group", +- user_name, AUDIT_NO_ID, ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "delete-shadow-group", ++ user_name, AUDIT_NO_ID, user_name, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ + SYSLOG ((LOG_INFO, +@@ -478,7 +478,7 @@ static void fail_exit (int code) + + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user", ++ "delete-user", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -498,24 +498,12 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + pw_locked = true; + if (pw_open (O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, pw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + if (is_shadow_pwd) { +@@ -523,12 +511,6 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking shadow password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + spw_locked = true; +@@ -536,12 +518,6 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening shadow password file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_PW_UPDATE); + } + } +@@ -549,23 +525,11 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + gr_locked = true; + if (gr_open (O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + #ifdef SHADOWGRP +@@ -574,24 +538,12 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "locking shadow group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + sgr_locked= true; + if (sgr_open (O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_USER, Prog, +- "opening shadow group file", +- user_name, (unsigned int) user_id, +- SHADOW_AUDIT_FAILURE); +-#endif /* WITH_AUDIT */ + fail_exit (E_GRP_UPDATE); + } + } +@@ -622,7 +574,7 @@ static void update_user (void) + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user entries", ++ "delete-user", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + #endif /* WITH_AUDIT */ +@@ -716,7 +668,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -732,7 +684,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -742,8 +694,8 @@ static int remove_mailbox (void) + #ifdef WITH_AUDIT + else + { +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + } +@@ -760,7 +712,7 @@ static int remove_mailbox (void) + mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -775,7 +727,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -785,8 +737,8 @@ static int remove_mailbox (void) + #ifdef WITH_AUDIT + else + { +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting mail file", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "delete-mail-file", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + } +@@ -980,7 +932,7 @@ int main (int argc, char **argv) + Prog, user_name); + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user not found", ++ "deleting-user-not-found", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -1024,7 +976,7 @@ int main (int argc, char **argv) + if (!fflg) { + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting user logged in", ++ "deleting-user-logged-in", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -1101,8 +1053,8 @@ int main (int argc, char **argv) + #ifdef WITH_AUDIT + else + { +- audit_logger (AUDIT_DEL_USER, Prog, +- "deleting home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "deleting-home-directory", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_SUCCESS); + } +@@ -1111,7 +1063,7 @@ int main (int argc, char **argv) + #ifdef WITH_AUDIT + if (0 != errors) { + audit_logger (AUDIT_DEL_USER, Prog, +- "deleting home directory", ++ "deleting-home-directory", + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + } +@@ -1124,8 +1076,8 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), + Prog, user_name); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "removing SELinux user mapping", ++ audit_logger (AUDIT_ROLE_REMOVE, Prog, ++ "delete-selinux-user-mapping", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +diff -urp shadow-4.1.5.1.orig/src/usermod.c shadow-4.1.5.1/src/usermod.c +--- shadow-4.1.5.1.orig/src/usermod.c 2014-09-13 15:45:55.013829557 -0400 ++++ shadow-4.1.5.1/src/usermod.c 2014-10-14 08:50:05.817817855 -0400 +@@ -352,8 +352,8 @@ static char *new_pw_passwd (char *pw_pas + + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "updating passwd", +- user_newname, (unsigned int) user_newid, 0); ++ "updating-password", ++ user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); + strcpy (buf, "!"); +@@ -372,8 +372,8 @@ static char *new_pw_passwd (char *pw_pas + + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "updating password", +- user_newname, (unsigned int) user_newid, 0); ++ "updating-password", ++ user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); + s = pw_pass; +@@ -384,7 +384,7 @@ static char *new_pw_passwd (char *pw_pas + } else if (pflg) { + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing password", ++ "updating-password", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); +@@ -413,8 +413,8 @@ static void new_pwent (struct passwd *pw + fail_exit (E_NAME_IN_USE); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing name", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-name", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -434,8 +434,8 @@ static void new_pwent (struct passwd *pw + + if (uflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing uid", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-uid", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -445,8 +445,8 @@ static void new_pwent (struct passwd *pw + } + if (gflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing primary group", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-primary-group", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -456,8 +456,8 @@ static void new_pwent (struct passwd *pw + } + if (cflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing comment", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-comment", + user_newname, (unsigned int) user_newid, 1); + #endif + pwent->pw_gecos = user_newcomment; +@@ -465,8 +465,8 @@ static void new_pwent (struct passwd *pw + + if (dflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-home-dir", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -476,8 +476,8 @@ static void new_pwent (struct passwd *pw + } + if (sflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing user shell", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-shell", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -507,8 +507,8 @@ static void new_spent (struct spwd *spen + + if (fflg) { + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing inactive days", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-inactive-days", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -524,8 +524,8 @@ static void new_spent (struct spwd *spen + date_to_str (old_exp, sizeof(old_exp), + user_expire * DAY); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing expiration date", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "changing-expiration-date", + user_newname, (unsigned int) user_newid, 1); + #endif + SYSLOG ((LOG_INFO, +@@ -592,9 +592,9 @@ static /*@noreturn@*/void fail_exit (int + } + + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "modifying account", +- user_name, AUDIT_NO_ID, 0); ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "modify-account", ++ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); + #endif + exit (code); + } +@@ -648,9 +648,12 @@ static void update_group (void) + user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing group member", +- user_newname, AUDIT_NO_ID, 1); ++ audit_logger_with_group ( ++ AUDIT_USER_MGMT, Prog, ++ "update-member-in-group", ++ user_newname, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "change '%s' to '%s' in group '%s'", +@@ -664,9 +667,11 @@ static void update_group (void) + ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "removing group member", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user_name, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "delete '%s' from group '%s'", +@@ -679,9 +684,11 @@ static void update_group (void) + ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user_name, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, "add '%s' to group '%s'", + user_newname, ngrp->gr_name)); +@@ -756,9 +763,10 @@ static void update_gshadow (void) + nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing admin name in shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "update-admin-name-in-group", ++ user_name, AUDIT_NO_ID, nsgrp->sg_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "change admin '%s' to '%s' in shadow group '%s'", +@@ -778,9 +786,10 @@ static void update_gshadow (void) + user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing member in shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "update-member-in-group", ++ user_name, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, + "change '%s' to '%s' in shadow group '%s'", +@@ -794,9 +803,10 @@ static void update_gshadow (void) + nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "removing user from shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "delete-user-from-group", ++ user_name, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, + "delete '%s' from shadow group '%s'", +@@ -809,9 +819,10 @@ static void update_gshadow (void) + nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to shadow group", +- user_newname, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user_newname, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", + user_newname, nsgrp->sg_name)); +@@ -1515,8 +1526,8 @@ static void move_home (void) + + #ifdef WITH_AUDIT + if (uflg || gflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing home directory owner", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-home-dir-owner", + user_newname, (unsigned int) user_newid, 1); + } + #endif +@@ -1534,8 +1545,8 @@ static void move_home (void) + fail_exit (E_HOMEDIR); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "moving home directory", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "moving-home-dir", + user_newname, (unsigned int) user_newid, + 1); + #endif +@@ -1554,9 +1565,9 @@ static void move_home (void) + Prog, user_home); + } + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, ++ audit_logger (AUDIT_USER_MGMT, + Prog, +- "moving home directory", ++ "moving-home-dir", + user_newname, + (unsigned int) user_newid, + 1); +@@ -1760,8 +1771,8 @@ static void move_mailbox (void) + } + #ifdef WITH_AUDIT + else { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing mail file owner", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-mail-file-owner", + user_newname, (unsigned int) user_newid, 1); + } + #endif +@@ -1779,8 +1790,8 @@ static void move_mailbox (void) + } + #ifdef WITH_AUDIT + else { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing mail file name", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-mail-file-name", + user_newname, (unsigned int) user_newid, 1); + } + #endif +@@ -1910,8 +1921,8 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), + Prog, user_name, user_selinux); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "modifying User mapping ", ++ audit_logger (AUDIT_ROLE_ASSIGN, Prog, ++ "changing-selinux-user-mapping ", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -1923,8 +1934,8 @@ int main (int argc, char **argv) + _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), + Prog, user_name); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, +- "removing SELinux user mapping", ++ audit_logger (AUDIT_ROLE_REMOVE, Prog, ++ "delete-selinux-user-mapping", + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +@@ -1962,8 +1973,8 @@ int main (int argc, char **argv) + */ + #ifdef WITH_AUDIT + if (uflg || gflg) { +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing home directory owner", ++ audit_logger (AUDIT_USER_MGMT, Prog, ++ "updating-home-dir-owner", + user_newname, (unsigned int) user_newid, 1); + } + #endif diff --git a/shadow-4.1.5.1-group-alloc.patch b/shadow-4.1.5.1-id-alloc.patch similarity index 52% rename from shadow-4.1.5.1-group-alloc.patch rename to shadow-4.1.5.1-id-alloc.patch index 0ac336b..df6f89f 100644 --- a/shadow-4.1.5.1-group-alloc.patch +++ b/shadow-4.1.5.1-id-alloc.patch @@ -1,8 +1,3 @@ -From e551be23be24508ecf5c8afdf74fd69b88832ecd Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Mon, 9 Jun 2014 10:34:02 -0400 -Subject: [PATCH] Redesign automatic GID allocation - Previously, this allocation was optimized for an outdated deployment style (that of /etc/group alongside nss_db). The issue here is that this results in extremely poor performance when using @@ -44,14 +39,13 @@ we come to the first unused GID. We then select that and return it. If we make it through all the remaining IDs without finding a free one, we start over from the beginning of the range and try to find room in one of the gaps in the range. ---- - libmisc/find_new_gid.c | 533 +++++++++++++++++++++++++++++++++++++------------ - 1 file changed, 407 insertions(+), 126 deletions(-) -diff --git a/libmisc/find_new_gid.c b/libmisc/find_new_gid.c -index 05f5622edb79069d9a43d3f9c69a463b6b71141a..25900dd12874e46e5efdfcf7c895f6b814763a16 100644 ---- a/libmisc/find_new_gid.c -+++ b/libmisc/find_new_gid.c +The patch was originally written by Stephen Gallagher and applied +identically also to the user allocation by Tomáš Mráz. + +diff -up shadow-4.1.5.1/libmisc/find_new_gid.c.id-alloc shadow-4.1.5.1/libmisc/find_new_gid.c +--- shadow-4.1.5.1/libmisc/find_new_gid.c.id-alloc 2014-09-10 10:25:41.165524986 +0200 ++++ shadow-4.1.5.1/libmisc/find_new_gid.c 2014-09-10 10:25:41.195525677 +0200 @@ -39,6 +39,118 @@ #include "getdef.h" @@ -302,6 +296,11 @@ index 05f5622edb79069d9a43d3f9c69a463b6b71141a..25900dd12874e46e5efdfcf7c895f6b8 - free (used_gids); - return 0; - } +- +- /* if we did not find free preffered system gid, we start to look for +- * one in the range assigned to dynamic system IDs */ +- if (sys_group) +- gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); + /* First look for the lowest and highest value in the local database */ + (void) gr_rewind (); + highest_found = gid_min; @@ -326,11 +325,7 @@ index 05f5622edb79069d9a43d3f9c69a463b6b71141a..25900dd12874e46e5efdfcf7c895f6b8 + /* create index of used GIDs */ + if (grp->gr_gid >= gid_min + && grp->gr_gid <= gid_max) { - -- /* if we did not find free preffered system gid, we start to look for -- * one in the range assigned to dynamic system IDs */ -- if (sys_group) -- gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); ++ + used_gids[grp->gr_gid] = true; + } + } @@ -350,16 +345,17 @@ index 05f5622edb79069d9a43d3f9c69a463b6b71141a..25900dd12874e46e5efdfcf7c895f6b8 - * Since there is a limited amount of IDs to be tested - * for system accounts, we just check the existence - * of IDs with getgrgid. -+ /* -+ * For system groups, we want to start from the -+ * top of the range and work downwards. - */ +- */ - group_id = gid_max; - for (id = gid_max; id >= gid_min; id--) { - if (getgrgid (id) != NULL) { - group_id = id - 1; - used_gids[id] = true; - } ++ /* ++ * For system groups, we want to start from the ++ * top of the range and work downwards. ++ */ + + /* + * At the conclusion of the gr_next() search, we will either @@ -637,6 +633,587 @@ index 05f5622edb79069d9a43d3f9c69a463b6b71141a..25900dd12874e46e5efdfcf7c895f6b8 + return -1; } --- -1.9.3 - +diff -up shadow-4.1.5.1/libmisc/find_new_uid.c.id-alloc shadow-4.1.5.1/libmisc/find_new_uid.c +--- shadow-4.1.5.1/libmisc/find_new_uid.c.id-alloc 2011-07-29 17:39:16.000000000 +0200 ++++ shadow-4.1.5.1/libmisc/find_new_uid.c 2014-10-17 16:52:30.481217270 +0200 +@@ -39,6 +39,118 @@ + #include "getdef.h" + + /* ++ * get_ranges - Get the minimum and maximum ID ranges for the search ++ * ++ * This function will return the minimum and maximum ranges for IDs ++ * ++ * 0: The function completed successfully ++ * EINVAL: The provided ranges are impossible (such as maximum < minimum) ++ * ++ * preferred_min: The special-case minimum value for a specifically- ++ * requested ID, which may be lower than the standard min_id ++ */ ++static int get_ranges(bool sys_user, uid_t *min_id, uid_t *max_id, ++ uid_t *preferred_min) ++{ ++ uid_t uid_def_max = 0; ++ ++ if (sys_user) { ++ /* System users */ ++ ++ /* A requested ID is allowed to be below the autoselect range */ ++ *preferred_min = (uid_t) 1; ++ ++ /* Get the minimum ID range from login.defs or default to 101 */ ++ *min_id = (uid_t) getdef_ulong("SYS_UID_MIN", 101UL); ++ ++ /* ++ * If SYS_UID_MAX is unspecified, we should assume it to be one ++ * less than the UID_MIN (which is reserved for non-system accounts) ++ */ ++ uid_def_max = (uid_t) getdef_ulong("UID_MIN", 1000UL) - 1; ++ *max_id = (uid_t) getdef_ulong("SYS_UID_MAX", ++ (unsigned long) uid_def_max); ++ ++ /* Check that the ranges make sense */ ++ if (*max_id < *min_id) { ++ (void) fprintf (stderr, ++ _("%s: Invalid configuration: SYS_UID_MIN (%lu), " ++ "UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), ++ Prog, (unsigned long) *min_id, ++ getdef_ulong ("UID_MIN", 1000UL), ++ (unsigned long) *max_id); ++ return EINVAL; ++ } ++ } else { ++ /* Non-system users */ ++ ++ /* Get the values from login.defs or use reasonable defaults */ ++ *min_id = (uid_t) getdef_ulong("UID_MIN", 1000UL); ++ *max_id = (uid_t) getdef_ulong("UID_MAX", 60000UL); ++ ++ /* ++ * The preferred minimum should match the standard ID minimum ++ * for non-system users. ++ */ ++ *preferred_min = *min_id; ++ ++ /* Check that the ranges make sense */ ++ if (*max_id < *min_id) { ++ (void) fprintf(stderr, ++ _("%s: Invalid configuration: UID_MIN (%lu), " ++ "UID_MAX (%lu)\n"), ++ Prog, (unsigned long) *min_id, ++ (unsigned long) *max_id); ++ return EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * check_uid - See if the requested UID is available ++ * ++ * On success, return 0 ++ * If the ID is in use, return EEXIST ++ * If the ID is outside the range, return ERANGE ++ * In other cases, return errno from getpwuid() ++ */ ++static int check_uid(const uid_t uid, ++ const uid_t uid_min, ++ const uid_t uid_max, ++ bool *used_uids) ++{ ++ /* First test that the preferred ID is in the range */ ++ if (uid < uid_min || uid > uid_max) { ++ return ERANGE; ++ } ++ ++ /* ++ * Check whether we already detected this UID ++ * using the pw_next() loop ++ */ ++ if (used_uids != NULL && used_uids[uid]) { ++ return EEXIST; ++ } ++ /* Check if the UID exists according to NSS */ ++ errno = 0; ++ if (getpwuid(uid) != NULL) { ++ return EEXIST; ++ } else { ++ /* getpwuid() was NULL, check whether this was ++ * due to an error, so we can report it. ++ */ ++ /* ignore errors for now * if (errno != 0) { ++ return errno; ++ } */ ++ } ++ ++ /* If we've made it here, the UID must be available */ ++ return 0; ++} ++ ++/* + * find_new_uid - Find a new unused UID. + * + * If successful, find_new_uid provides an unused user ID in the +@@ -48,162 +160,339 @@ + * + * Return 0 on success, -1 if no unused UIDs are available. + */ +-int find_new_uid (bool sys_user, +- uid_t *uid, +- /*@null@*/uid_t const *preferred_uid) ++int find_new_uid(bool sys_user, ++ uid_t *uid, ++ /*@null@*/uid_t const *preferred_uid) + { +- const struct passwd *pwd; +- uid_t uid_min, uid_max, user_id; + bool *used_uids; ++ const struct passwd *pwd; ++ uid_t uid_min, uid_max, preferred_min; ++ uid_t user_id, id; ++ uid_t lowest_found, highest_found; ++ int result; ++ int nospam = 0; + + assert (uid != NULL); + +- if (!sys_user) { +- uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); +- uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); +- if (uid_max < uid_min) { +- (void) fprintf (stderr, +- _("%s: Invalid configuration: UID_MIN (%lu), UID_MAX (%lu)\n"), +- Prog, (unsigned long) uid_min, (unsigned long) uid_max); +- return -1; +- } +- } else { +- uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL); +- uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1; +- uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); +- if (uid_max < uid_min) { +- (void) fprintf (stderr, +- _("%s: Invalid configuration: SYS_UID_MIN (%lu), UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), +- Prog, (unsigned long) uid_min, getdef_ulong ("UID_MIN", 1000UL), (unsigned long) uid_max); ++ /* ++ * First, figure out what ID range is appropriate for ++ * automatic assignment ++ */ ++ result = get_ranges(sys_user, &uid_min, &uid_max, &preferred_min); ++ if (result == EINVAL) { ++ return -1; ++ } ++ ++ /* Check if the preferred UID is available */ ++ if (preferred_uid) { ++ result = check_uid(*preferred_uid, preferred_min, uid_max, NULL); ++ if (result == 0) { ++ /* ++ * Make sure the UID isn't queued for use already ++ */ ++ if (pw_locate_uid (*preferred_uid) == NULL) { ++ *uid = *preferred_uid; ++ return 0; ++ } ++ /* ++ * pw_locate_uid() found the UID in an as-yet uncommitted ++ * entry. We'll proceed below and auto-set an UID. ++ */ ++ } else if (result == EEXIST || result == ERANGE) { ++ /* ++ * Continue on below. At this time, we won't ++ * treat these two cases differently. ++ */ ++ } else { ++ /* ++ * An unexpected error occurred. We should report ++ * this and fail the user creation. ++ * This differs from the automatic creation ++ * behavior below, since if a specific UID was ++ * requested and generated an error, the user is ++ * more likely to want to stop and address the ++ * issue. ++ */ ++ fprintf(stderr, ++ _("%s: Encountered error attempting to use " ++ "preferred UID: %s\n"), ++ Prog, strerror(result)); + return -1; + } + } ++ ++ /* ++ * Search the entire passwd file, ++ * looking for the next unused value. ++ * ++ * We first check the local database with pw_rewind/pw_next to find ++ * all local values that are in use. ++ * ++ * We then compare the next free value to all databases (local and ++ * remote) and iterate until we find a free one. If there are free ++ * values beyond the lowest (system users) or highest (non-system ++ * users), we will prefer those and avoid potentially reclaiming a ++ * deleted user (which can be a security issue, since it may grant ++ * access to files belonging to that former user). ++ * ++ * If there are no UIDs available at the end of the search, we will ++ * have no choice but to iterate through the range looking for gaps. ++ * ++ */ ++ ++ /* Create an array to hold all of the discovered UIDs */ + used_uids = malloc (sizeof (bool) * (uid_max +1)); + if (NULL == used_uids) { + fprintf (stderr, +- _("%s: failed to allocate memory: %s\n"), +- Prog, strerror (errno)); ++ _("%s: failed to allocate memory: %s\n"), ++ Prog, strerror (errno)); + return -1; + } + memset (used_uids, false, sizeof (bool) * (uid_max + 1)); + +- if ( (NULL != preferred_uid) +- && (*preferred_uid >= uid_min) +- && (*preferred_uid <= uid_max) +- /* Check if the user exists according to NSS */ +- && (getpwuid (*preferred_uid) == NULL) +- /* Check also the local database in case of uncommitted +- * changes */ +- && (pw_locate_uid (*preferred_uid) == NULL)) { +- *uid = *preferred_uid; +- free (used_uids); +- return 0; +- } ++ /* First look for the lowest and highest value in the local database */ ++ (void) pw_rewind (); ++ highest_found = uid_min; ++ lowest_found = uid_max; ++ while ((pwd = pw_next ()) != NULL) { ++ /* ++ * Does this entry have a lower UID than the lowest we've found ++ * so far? ++ */ ++ if ((pwd->pw_uid <= lowest_found) && (pwd->pw_uid >= uid_min)) { ++ lowest_found = pwd->pw_uid - 1; ++ } + ++ /* ++ * Does this entry have a higher UID than the highest we've found ++ * so far? ++ */ ++ if ((pwd->pw_uid >= highest_found) && (pwd->pw_uid <= uid_max)) { ++ highest_found = pwd->pw_uid + 1; ++ } ++ ++ /* create index of used UIDs */ ++ if (pwd->pw_uid >= uid_min ++ && pwd->pw_uid <= uid_max) { ++ ++ used_uids[pwd->pw_uid] = true; ++ } ++ } + +- /* +- * Search the entire password file, +- * looking for the largest unused value. +- * +- * We check the list of users according to NSS (setpwent/getpwent), +- * but we also check the local database (pw_rewind/pw_next) in case +- * some users were created but the changes were not committed yet. +- */ + if (sys_user) { +- uid_t id; +- /* setpwent / getpwent / endpwent can be very slow with +- * LDAP configurations (and many accounts). +- * Since there is a limited amount of IDs to be tested +- * for system accounts, we just check the existence +- * of IDs with getpwuid. +- */ +- user_id = uid_max; +- for (id = uid_max; id >= uid_min; id--) { +- if (getpwuid (id) != NULL) { +- user_id = id - 1; +- used_uids[id] = true; +- } ++ /* ++ * For system users, we want to start from the ++ * top of the range and work downwards. ++ */ ++ ++ /* ++ * At the conclusion of the pw_next() search, we will either ++ * have a presumed-free UID or we will be at UID_MIN - 1. ++ */ ++ if (lowest_found < uid_min) { ++ /* ++ * In this case, an UID is in use at UID_MIN. ++ * ++ * We will reset the search to UID_MAX and proceed down ++ * through all the UIDs (skipping those we detected with ++ * used_uids) for a free one. It is a known issue that ++ * this may result in reusing a previously-deleted UID, ++ * so administrators should be instructed to use this ++ * auto-detection with care (and prefer to assign UIDs ++ * explicitly). ++ */ ++ lowest_found = uid_max; + } + +- (void) pw_rewind (); +- while ((pwd = pw_next ()) != NULL) { +- if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) { +- user_id = pwd->pw_uid - 1; +- } +- /* create index of used UIDs */ +- if (pwd->pw_uid <= uid_max) { +- used_uids[pwd->pw_uid] = true; ++ /* Search through all of the IDs in the range */ ++ for (id = lowest_found; id >= uid_min; id--) { ++ result = check_uid(id, uid_min, uid_max, used_uids); ++ if (result == 0) { ++ /* This UID is available. Return it. */ ++ *uid = id; ++ free(used_uids); ++ return 0; ++ } else if (result == EEXIST) { ++ /* This UID is in use, we'll continue to the next */ ++ } else { ++ /* ++ * An unexpected error occurred. ++ * ++ * Only report it the first time to avoid spamming ++ * the logs ++ * ++ */ ++ if (!nospam) { ++ fprintf(stderr, ++ _("%s: Can't get unique system UID (%s). " ++ "Suppressing additional messages.\n"), ++ Prog, strerror(result)); ++ SYSLOG((LOG_ERR, ++ "Error checking available UIDs: %s", ++ strerror(result))); ++ nospam = 1; ++ } ++ /* ++ * We will continue anyway. Hopefully a later UID ++ * will work properly. ++ */ + } + } +- } else { +- user_id = uid_min; +- setpwent (); +- while ((pwd = getpwent ()) != NULL) { +- if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { +- user_id = pwd->pw_uid + 1; +- } +- /* create index of used UIDs */ +- if (pwd->pw_uid <= uid_max) { +- used_uids[pwd->pw_uid] = true; ++ ++ /* ++ * If we get all the way through the loop, try again from UID_MAX, ++ * unless that was where we previously started. (NOTE: the worst-case ++ * scenario here is that we will run through (UID_MAX - UID_MIN - 1) ++ * cycles *again* if we fall into this case with lowest_found as ++ * UID_MAX - 1, all users in the range in use and maintained by ++ * network services such as LDAP.) ++ */ ++ if (lowest_found != uid_max) { ++ for (id = uid_max; id >= uid_min; id--) { ++ result = check_uid(id, uid_min, uid_max, used_uids); ++ if (result == 0) { ++ /* This UID is available. Return it. */ ++ *uid = id; ++ free(used_uids); ++ return 0; ++ } else if (result == EEXIST) { ++ /* This UID is in use, we'll continue to the next */ ++ } else { ++ /* ++ * An unexpected error occurred. ++ * ++ * Only report it the first time to avoid spamming ++ * the logs ++ * ++ */ ++ if (!nospam) { ++ fprintf(stderr, ++ _("%s: Can't get unique system UID (%s). " ++ "Suppressing additional messages.\n"), ++ Prog, strerror(result)); ++ SYSLOG((LOG_ERR, ++ "Error checking available UIDs: %s", ++ strerror(result))); ++ nospam = 1; ++ } ++ /* ++ * We will continue anyway. Hopefully a later UID ++ * will work properly. ++ */ ++ } + } + } +- endpwent (); ++ } else { /* !sys_user */ ++ /* ++ * For non-system users, we want to start from the ++ * bottom of the range and work upwards. ++ */ + +- (void) pw_rewind (); +- while ((pwd = pw_next ()) != NULL) { +- if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { +- user_id = pwd->pw_uid + 1; +- } +- /* create index of used UIDs */ +- if (pwd->pw_uid <= uid_max) { +- used_uids[pwd->pw_uid] = true; +- } ++ /* ++ * At the conclusion of the pw_next() search, we will either ++ * have a presumed-free UID or we will be at UID_MAX + 1. ++ */ ++ if (highest_found > uid_max) { ++ /* ++ * In this case, a UID is in use at UID_MAX. ++ * ++ * We will reset the search to UID_MIN and proceed up ++ * through all the UIDs (skipping those we detected with ++ * used_uids) for a free one. It is a known issue that ++ * this may result in reusing a previously-deleted UID, ++ * so administrators should be instructed to use this ++ * auto-detection with care (and prefer to assign UIDs ++ * explicitly). ++ */ ++ highest_found = uid_min; + } +- } + +- /* +- * If a user (resp. system user) with UID equal to UID_MAX (resp. +- * UID_MIN) exists, the above algorithm will give us UID_MAX+1 +- * (resp. UID_MIN-1) even if not unique. Search for the first free +- * UID starting with UID_MIN (resp. UID_MAX). +- */ +- if (sys_user) { +- if (user_id < uid_min) { +- for (user_id = uid_max; user_id >= uid_min; user_id--) { +- if (false == used_uids[user_id]) { +- break; ++ /* Search through all of the IDs in the range */ ++ for (id = highest_found; id <= uid_max; id++) { ++ result = check_uid(id, uid_min, uid_max, used_uids); ++ if (result == 0) { ++ /* This UID is available. Return it. */ ++ *uid = id; ++ free(used_uids); ++ return 0; ++ } else if (result == EEXIST) { ++ /* This UID is in use, we'll continue to the next */ ++ } else { ++ /* ++ * An unexpected error occurred. ++ * ++ * Only report it the first time to avoid spamming ++ * the logs ++ * ++ */ ++ if (!nospam) { ++ fprintf(stderr, ++ _("%s: Can't get unique UID (%s). " ++ "Suppressing additional messages.\n"), ++ Prog, strerror(result)); ++ SYSLOG((LOG_ERR, ++ "Error checking available UIDs: %s", ++ strerror(result))); ++ nospam = 1; + } +- } +- if (user_id < uid_min ) { +- fprintf (stderr, +- _("%s: Can't get unique system UID (no more available UIDs)\n"), +- Prog); +- SYSLOG ((LOG_WARN, +- "no more available UID on the system")); +- free (used_uids); +- return -1; ++ /* ++ * We will continue anyway. Hopefully a later UID ++ * will work properly. ++ */ + } + } +- } else { +- if (user_id > uid_max) { +- for (user_id = uid_min; user_id <= uid_max; user_id++) { +- if (false == used_uids[user_id]) { +- break; ++ ++ /* ++ * If we get all the way through the loop, try again from UID_MIN, ++ * unless that was where we previously started. (NOTE: the worst-case ++ * scenario here is that we will run through (UID_MAX - UID_MIN - 1) ++ * cycles *again* if we fall into this case with highest_found as ++ * UID_MIN + 1, all users in the range in use and maintained by ++ * network services such as LDAP.) ++ */ ++ if (highest_found != uid_min) { ++ for (id = uid_min; id <= uid_max; id++) { ++ result = check_uid(id, uid_min, uid_max, used_uids); ++ if (result == 0) { ++ /* This UID is available. Return it. */ ++ *uid = id; ++ free(used_uids); ++ return 0; ++ } else if (result == EEXIST) { ++ /* This UID is in use, we'll continue to the next */ ++ } else { ++ /* ++ * An unexpected error occurred. ++ * ++ * Only report it the first time to avoid spamming ++ * the logs ++ * ++ */ ++ if (!nospam) { ++ fprintf(stderr, ++ _("%s: Can't get unique UID (%s). " ++ "Suppressing additional messages.\n"), ++ Prog, strerror(result)); ++ SYSLOG((LOG_ERR, ++ "Error checking available UIDs: %s", ++ strerror(result))); ++ nospam = 1; ++ } ++ /* ++ * We will continue anyway. Hopefully a later UID ++ * will work properly. ++ */ + } + } +- if (user_id > uid_max) { +- fprintf (stderr, +- _("%s: Can't get unique UID (no more available UIDs)\n"), +- Prog); +- SYSLOG ((LOG_WARN, "no more available UID on the system")); +- free (used_uids); +- return -1; +- } + } + } + +- free (used_uids); +- *uid = user_id; +- return 0; ++ /* The code reached here and found no available IDs in the range */ ++ fprintf(stderr, ++ _("%s: Can't get unique UID (no more available UIDs)\n"), ++ Prog); ++ SYSLOG((LOG_WARN, "no more available UIDs on the system")); ++ free(used_uids); ++ return -1; + } + diff --git a/shadow-utils.spec b/shadow-utils.spec index e3d6b90..f1edde1 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,7 +1,7 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils Version: 4.1.5.1 -Release: 20%{?dist} +Release: 21%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ Source0: http://pkg-shadow.alioth.debian.org/releases/shadow-%{version}.tar.bz2 @@ -26,10 +26,11 @@ Patch14: shadow-4.1.5.1-default-range.patch Patch15: shadow-4.1.5.1-manfix.patch Patch16: shadow-4.1.5.1-crypt-null.patch Patch17: shadow-4.1.5.1-userdel-helpfix.patch -Patch18: shadow-4.1.5.1-group-alloc.patch +Patch18: shadow-4.1.5.1-id-alloc.patch Patch19: shadow-4.1.5.1-date-parsing.patch Patch20: shadow-4.1.5.1-ingroup.patch Patch21: shadow-4.1.5.1-move-home.patch +Patch22: shadow-4.1.5.1-audit-update.patch License: BSD and GPLv2+ Group: System Environment/Base @@ -75,10 +76,11 @@ are used for managing group accounts. %patch15 -p1 -b .manfix %patch16 -p1 -b .crypt-null %patch17 -p1 -b .userdel -%patch18 -p1 -b .group-alloc +%patch18 -p1 -b .id-alloc %patch19 -p1 -b .date-parsing %patch20 -p1 -b .ingroup %patch21 -p1 -b .move-home +%patch22 -p1 -b .audit-update iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -236,6 +238,11 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man8/vigr.8* %changelog +* Fri Oct 17 2014 Tomáš Mráz - 2:4.1.5.1-21 +- update auditing to cover more events and fix some incorrect audit + records - patch by Steve Grubb (#1151580) +- apply the same new allocation algorithm to uids as for gids + * Wed Sep 10 2014 Tomas Mraz - 2:4.1.5.1-20 - discard obsolete matchpathcon cache after semanage_commit()