audit

Peter Vrabec <[email protected]> Mon, 05 Sep 2005 14:03:34 +0000
Newsgroups gmane.linux.pld.shadow.general
Message-ID <[email protected]>
Here we go.

Tomasz Kłoczko wrote:
> On Thu, 1 Sep 2005, Peter Vrabec wrote:
> 
> 
>>Hi Tomasz,
>>
>>could u check audit support in attached shadow-utils release. See
>>https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=159215.
>>
>>I have transformed shadow-4.0.3-audit.patch from rhel-4 to
>>shadow-4.0.12-audit.patch. If u like it, i can do the same patch against 
>>current CVS version.
> 
> 
> Look very good and I'll be glad to see patch against CVS tree.
> 
> kloczek
shadow-audit.patch (text/x-patch, 49 KB)
--- shadow/configure.in.audit	2005-08-30 20:10:25.000000000 +0000
+++ shadow/configure.in	2005-09-05 13:38:05.000000000 +0000
@@ -226,6 +226,8 @@
 	[AC_HELP_STRING([--with-skey], [use S/Key support(default=no)])])
 AC_ARG_WITH(libcrack,
 	[AC_HELP_STRING([--with-libcrack], [use libcrack (default=yes if found and if PAM not enabled)])])
+AC_ARG_WITH(libaudit, 
+	[AC_HELP_STRING([--with-audit], [try to use audit (default=yes if found)])])
 
 dnl Check for some functions in libc first, only if not found check for
 dnl other libraries.  This should prevent linking libnsl if not really
@@ -260,6 +262,14 @@
 AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
 	[AC_MSG_ERROR([crypt() not found])])
 
+AC_SUBST(AUDIT)
+if test "$with_audit" != "no"; then
+       AC_CHECK_HEADER(libaudit.h, [ audit_header="yes" ], [ audit_header="no" ])
+       if test "$audit_header" = "yes"; then
+               AC_CHECK_LIB(audit, audit_send_message_if_enabled, AC_DEFINE(WITH_AUDIT,1,[Define if you want to enable Audit messages]) [LIBS="-Wl,-Bstatic -laudit -Wl,-dy $LIBS"])
+       fi
+fi
+
 AC_SUBST(LIBCRACK)
 if test "$with_libcrack" = "yes"; then
 	echo "checking cracklib flavour, don't be surprised by the results"
--- shadow/lib/prototypes.h.audit	2005-08-02 10:50:51.000000000 +0000
+++ shadow/lib/prototypes.h	2005-09-05 13:38:05.000000000 +0000
@@ -87,6 +87,18 @@
 /* hushed.c */
 extern int hushed (const struct passwd *);
 
+/* audit_help.c */
+#ifdef WITH_AUDIT
+extern int audit_fd;
+#endif
+void audit_help_open(void);
+void audit_help_log(const char *, ...)
+#ifdef __GNUC__
+       __attribute__ ((format (printf, 1, 2)));
+#else
+       ;
+#endif
+
 /* limits.c */
 extern void setup_limits (const struct passwd *);
 
--- shadow/lib/defines.h.audit	2005-08-03 18:11:27.000000000 +0000
+++ shadow/lib/defines.h	2005-09-05 13:38:05.000000000 +0000
@@ -331,4 +331,16 @@
 #define SHADOW_PASSWD_STRING "x"
 #endif
 
+#ifdef WITH_AUDIT
+  #ifdef __u8 		/* in case we use pam < 0.80 */
+    #undef __u8
+  #endif
+  #ifdef __u32
+    #undef __u32
+  #endif
+
+  #include <libaudit.h>
+#endif
+
 #endif				/* _DEFINES_H_ */
+
--- shadow/libmisc/Makefile.am.audit	2005-07-07 08:40:27.000000000 +0000
+++ shadow/libmisc/Makefile.am	2005-09-05 13:38:05.000000000 +0000
@@ -24,6 +24,7 @@
 	getdate.h \
 	hushed.c \
 	isexpired.c \
+	audit_help.c \
 	limits.c \
 	list.c log.c \
 	loginprompt.c \
--- shadow/libmisc/audit_help.c.audit	2005-09-05 13:38:05.000000000 +0000
+++ shadow/libmisc/audit_help.c	2005-09-05 13:38:05.000000000 +0000
@@ -0,0 +1,76 @@
+/*
+ *  Audit helper functions used throughout shadow-utils
+ *
+ *  Copyright (C) 2005, Red Hat, Inc.
+ *
+ *  Redistributable under the same terms as the other elements of
+ *  shadow-utils.
+ */
+
+
+#include <config.h>
+
+#ifdef WITH_AUDIT
+
+#include <stdlib.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <libaudit.h>
+#include <errno.h>
+#include <stdio.h>
+int audit_fd;
+
+void audit_help_open(void)
+{
+	audit_fd = audit_open();
+	if (audit_fd < 0) {
+		/* You get these only when the kernel doesn't have
+		 * audit compiled in. */
+		if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+                               errno == EAFNOSUPPORT)
+			return;
+		fprintf(stderr, "Cannot open audit interface - aborting.\n");
+		exit(1);
+	}
+}
+
+/*
+ * 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 
+ *	  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.
+ * result - 1 is "success" and 0 is "failed"
+ */
+void audit_logger(int type, const char *pgname, const char *op, 
+	const char *name, unsigned int id, int result)
+{
+        if (audit_fd < 0)
+                return;
+        else {
+		char buf[PATH_MAX];
+		const char *success;
+
+		if (result)
+			success = "success";
+		else
+			success = "failed";
+
+		if (name)
+			snprintf(buf, sizeof(buf), "%s: op=%s acct=%s res=%s",
+				pgname, op, name, success);
+		else
+			snprintf(buf, sizeof(buf), "%s: op=%s id=%u res=%s",
+				pgname, op, id, success);
+
+		audit_send_user_message(audit_fd, type, buf);
+        }
+}
+
+#endif /* WITH_AUDIT */
+
--- shadow/src/groupdel.c.audit	2005-08-31 17:25:00.000000000 +0000
+++ shadow/src/groupdel.c	2005-09-05 13:38:05.000000000 +0000
@@ -54,6 +54,7 @@
 static char *group_name;
 static char *Prog;
 static int errors;
+static gid_t    group_id = -1;
 
 #ifdef	SHADOWGRP
 static int is_shadow_grp;
@@ -108,6 +109,9 @@
 		errors++;
 	}
 #endif				/* SHADOWGRP */
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", group_name,group_id,1);
+#endif
 	SYSLOG ((LOG_INFO, "remove group `%s'\n", group_name));
 	return;
 }
@@ -231,6 +235,10 @@
 	int retval;
 #endif
 
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
+
 	/*
 	 * Get my name so that I can use it to report errors.
 	 */
@@ -290,8 +298,14 @@
 	if (!(grp = getgrnam (group_name))) {
 		fprintf (stderr, _("%s: group %s does not exist\n"),
 			 Prog, group_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", group_name,-1,0);
+#endif
 		exit (E_NOTFOUND);
 	}
+
+	group_id = grp->gr_gid; /* LAUS */
+
 #ifdef	USE_NIS
 	/*
 	 * Make sure this isn't a NIS group
@@ -303,6 +317,9 @@
 		fprintf (stderr, _("%s: group %s is a NIS group\n"),
 			 Prog, group_name);
 
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", group_name,-1,0);
+#endif
 		if (!yp_get_default_domain (&nis_domain) &&
 		    !yp_master (nis_domain, "group.byname", &nis_master)) {
 			fprintf (stderr, _("%s: %s is the NIS master\n"),
@@ -345,6 +362,10 @@
 	if (retval == PAM_SUCCESS)
 		pam_end (pamh, PAM_SUCCESS);
 #endif				/* USE_PAM */
+        if(errors != 0)
+#ifdef WITH_AUDIT
+ 	       audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", group_name,-1,0);
+#endif
 	exit (errors == 0 ? E_SUCCESS : E_GRP_UPDATE);
 	/* NOT REACHED */
 }
--- shadow/src/groupadd.c.audit	2005-09-01 15:26:41.000000000 +0000
+++ shadow/src/groupadd.c	2005-09-05 13:38:05.000000000 +0000
@@ -183,6 +183,9 @@
 		fail_exit (E_GRP_UPDATE);
 	}
 #endif				/* SHADOWGRP */
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding group", group_name,group_id,1);
+#endif
 	SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u",
 		 group_name, (unsigned int) group_id));
 }
@@ -330,10 +333,16 @@
 {
 	if (!gr_lock ()) {
 		fprintf (stderr, _("%s: unable to lock group file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking group file", group_name,-1,0);
+#endif
 		exit (E_GRP_UPDATE);
 	}
 	if (!gr_open (O_RDWR)) {
 		fprintf (stderr, _("%s: unable to open group file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening group file", group_name,-1,0);
+#endif
 		fail_exit (E_GRP_UPDATE);
 	}
 #ifdef	SHADOWGRP
@@ -361,6 +370,10 @@
 	if (is_shadow_grp)
 		sgr_unlock ();
 #endif
+	if(code != E_SUCCESS)
+#ifdef WITH_AUDIT
+  		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding group", group_name,-1,0);
+#endif
 	exit (code);
 }
 
@@ -383,6 +396,9 @@
 	int retval;
 #endif
 
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
 	/*
 	 * Get my name so that I can use it to report errors.
 	 */
@@ -523,6 +539,9 @@
 			exit (E_SUCCESS);
 		}
 		fprintf (stderr, _("%s: group %s exists\n"), Prog, group_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding group", group_name,-1,0);
+#endif
 		exit (E_NAME_IN_USE);
 	}
 
--- shadow/src/useradd.c.audit	2005-09-01 15:26:41.000000000 +0000
+++ shadow/src/useradd.c	2005-09-05 13:38:05.000000000 +0000
@@ -194,6 +194,9 @@
 	if (home_added)
 		rmdir (user_home);
 
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user", user_name,-1, 0);
+#endif
 	SYSLOG ((LOG_INFO, "failed adding user `%s', data deleted", user_name));
 	exit (code);
 }
@@ -513,6 +516,9 @@
 		perror (buf);
 		return -1;
 	}
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing user defaults", NULL,-1, 1);
+#endif
 	SYSLOG ((LOG_INFO,
 		 "useradd defaults: GROUP=%u, HOME=%s, SHELL=%s, INACTIVE=%ld, "
 		 "EXPIRE=%s, SKEL=%s, CREATE_MAIL_SPOOL=%s",
@@ -793,6 +799,9 @@
 				 _("%s: error adding new group entry\n"), Prog);
 			fail_exit (E_GRP_UPDATE);
 		}
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user to group", user_name,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "add `%s' to group `%s'",
 			 user_name, ngrp->gr_name));
 	}
@@ -841,6 +850,9 @@
 				 _("%s: error adding new group entry\n"), Prog);
 			fail_exit (E_GRP_UPDATE);
 		}
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user to shadow group", user_name,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "add `%s' to shadow group `%s'",
 			 user_name, nsgrp->sg_name));
 	}
@@ -887,11 +899,17 @@
 		if (strcmp (user_name, pwd->pw_name) == 0) {
 			fprintf (stderr, _("%s: name %s is not unique\n"),
 				 Prog, user_name);
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user", user_name,user_id, 0);
+#endif
 			exit (E_NAME_IN_USE);
 		}
 		if (uflg && user_id == pwd->pw_uid) {
 			fprintf (stderr, _("%s: UID %u is not unique\n"),
 				 Prog, (unsigned int) user_id);
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user", user_name,user_id, 0);
+#endif
 			exit (E_UID_IN_USE);
 		}
 		if (!uflg && pwd->pw_uid >= user_id) {
@@ -1170,6 +1188,9 @@
 				 _
 				 ("%s: invalid user name '%s'\n"),
 				 Prog, user_name);
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user", user_name,-1, 0);
+#endif
 			exit (E_BAD_ARG);
 		}
 		if (!dflg) {
@@ -1244,22 +1265,34 @@
 {
 	if (!pw_lock ()) {
 		fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking password file", user_name,user_id, 0);
+#endif
 		exit (E_PW_UPDATE);
 	}
 	if (!pw_open (O_RDWR)) {
 		fprintf (stderr, _("%s: unable to open password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening password file", user_name,user_id, 0);
+#endif
 		pw_unlock ();
 		exit (E_PW_UPDATE);
 	}
 	if (is_shadow_pwd && !spw_lock ()) {
 		fprintf (stderr,
 			 _("%s: cannot lock shadow password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking shadow password file", user_name,user_id, 0);
+#endif
 		pw_unlock ();
 		exit (E_PW_UPDATE);
 	}
 	if (is_shadow_pwd && !spw_open (O_RDWR)) {
 		fprintf (stderr,
 			 _("%s: cannot open shadow password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening shadow password file", user_name,user_id, 0);
+#endif
 		spw_unlock ();
 		pw_unlock ();
 		exit (E_PW_UPDATE);
@@ -1359,9 +1392,16 @@
 			 _
 			 ("%s: error adding new shadow password entry\n"),
 			 Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding shadow password", user_name,user_id, 0);
+#endif
 		exit (E_PW_UPDATE);
 	}
 
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user", user_name, user_id, 1);
+#endif
+
 	/*
 	 * Do any group file updates for this user.
 	 */
@@ -1392,6 +1432,9 @@
 		chown (user_home, user_id, user_gid);
 		chmod (user_home, 0777 & ~getdef_num ("UMASK", 022));
 		home_added++;
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding home directory", user_name, user_id, 1);
+#endif
 	}
 }
 
@@ -1465,6 +1508,10 @@
 	struct passwd *pampw;
 	int retval;
 #endif
+	
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
 
 	/*
 	 * Get my name so that I can use it to report errors.
@@ -1541,6 +1588,9 @@
 
 	if (getpwnam (user_name)) {
 		fprintf (stderr, _("%s: user %s exists\n"), Prog, user_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user", user_name,-1, 0);
+#endif
 		exit (E_NAME_IN_USE);
 	}
 
@@ -1556,6 +1606,9 @@
 				 _
 				 ("%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_USER_CHAUTHTOK,Prog,"adding group", user_name,-1, 0);
+#endif
 			exit (E_NAME_IN_USE);
 		}
 	}
--- shadow/src/userdel.c.audit	2005-08-31 17:25:00.000000000 +0000
+++ shadow/src/userdel.c	2005-09-05 13:38:05.000000000 +0000
@@ -156,8 +156,10 @@
 
 		/*
 		 * Update the DBM group file with the new entry as well.
-		 */
-
+		 */		
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting user from group", user_name,user_id, 0);
+#endif
 		SYSLOG ((LOG_INFO, "delete `%s' from group `%s'\n",
 			 user_name, ngrp->gr_name));
 	}
@@ -177,6 +179,9 @@
 		deleted_user_group = 1;
 #endif
 
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", user_name,user_id, 0);
+#endif
 		SYSLOG ((LOG_INFO, "removed group `%s' owned by `%s'\n",
 			 grp->gr_name, user_name));
 	}
@@ -218,6 +223,9 @@
 		if (!sgr_update (nsgrp))
 			fprintf (stderr,
 				 _("%s: error updating group entry\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting user from shadow group", user_name,user_id, 0);
+#endif
 		SYSLOG ((LOG_INFO, "delete `%s' from shadow group `%s'\n",
 			 user_name, nsgrp->sg_name));
 	}
@@ -272,6 +280,9 @@
 	if (is_shadow_grp)
 		sgr_unlock ();
 #endif
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting user", user_name,user_id, 0);
+#endif
 	exit (code);
 }
 
@@ -285,39 +296,63 @@
 {
 	if (!pw_lock ()) {
 		fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking password file", user_name,user_id, 1, 0);
+#endif
 		exit (E_PW_UPDATE);
 	}
 	if (!pw_open (O_RDWR)) {
 		fprintf (stderr, _("%s: unable to open password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening password file", user_name,user_id, 0);
+#endif
 		fail_exit (E_PW_UPDATE);
 	}
 	if (is_shadow_pwd && !spw_lock ()) {
 		fprintf (stderr,
 			 _("%s: cannot lock shadow password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking shadow password file", user_name,user_id, 0);
+#endif
 		fail_exit (E_PW_UPDATE);
 	}
 	if (is_shadow_pwd && !spw_open (O_RDWR)) {
 		fprintf (stderr,
 			 _("%s: cannot open shadow password file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening shadow password file", user_name,user_id, 0);
+#endif
 		fail_exit (E_PW_UPDATE);
 	}
 	if (!gr_lock ()) {
 		fprintf (stderr, _("%s: unable to lock group file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking group file", user_name,user_id, 0);
+#endif
 		fail_exit (E_GRP_UPDATE);
 	}
 	if (!gr_open (O_RDWR)) {
 		fprintf (stderr, _("%s: cannot open group file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening group file", user_name,user_id, 0);
+#endif
 		fail_exit (E_GRP_UPDATE);
 	}
 #ifdef	SHADOWGRP
 	if (is_shadow_grp && !sgr_lock ()) {
 		fprintf (stderr,
 			 _("%s: unable to lock shadow group file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking shadow group file", user_name,user_id, 0);
+#endif
 		fail_exit (E_GRP_UPDATE);
 	}
 	if (is_shadow_grp && !sgr_open (O_RDWR)) {
 		fprintf (stderr, _("%s: cannot open shadow group file\n"),
 			 Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening shadow group file", user_name,user_id, 0);
+#endif
 		fail_exit (E_GRP_UPDATE);
 	}
 #endif
@@ -338,6 +373,9 @@
 	if (is_shadow_pwd && !spw_remove (user_name))
 		fprintf (stderr,
 			 _("%s: error deleting shadow password entry\n"), Prog);
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting user entries", user_name,user_id, 1);
+#endif
 	SYSLOG ((LOG_INFO, "delete user `%s'\n", user_name));
 }
 
@@ -378,7 +416,12 @@
 			continue;
 		fprintf (stderr,
 			 _("%s: user %s is currently logged in\n"), Prog, name);
-		exit (E_USER_BUSY);
+		if (!fflg) {
+#ifdef WITH_AUDIT
+	                audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting user logged in", name,-1, 0);
+#endif
+			exit (E_USER_BUSY);
+		}
 	}
 }
 
@@ -479,6 +522,9 @@
 	snprintf (mailfile, sizeof mailfile, "%s/%s", maildir, user_name);
 	if (fflg) {
 		unlink (mailfile);	/* always remove, ignore errors */
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting mail file", user_name,user_id, 1);
+#endif
 		return;
 	}
 	i = is_owner (user_id, mailfile);
@@ -487,6 +533,9 @@
 			 _
 			 ("%s: %s not owned by %s, not removing\n"),
 			 Prog, mailfile, user_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting mail file", user_name,user_id, 0);
+#endif
 		return;
 	} else if (i == -1)
 		return;		/* mailbox doesn't exist */
@@ -494,6 +543,11 @@
 		fprintf (stderr, _("%s: warning: can't remove "), Prog);
 		perror (mailfile);
 	}
+#ifdef WITH_AUDIT
+	else {
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting mail file", user_name,user_id, 0);
+	}
+#endif
 }
 
 #ifdef USE_PAM
@@ -515,6 +569,11 @@
 	struct passwd *pampw;
 	int retval;
 #endif
+	
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
+	
 	/*
 	 * Get my name so that I can use it to report errors.
 	 */
@@ -581,6 +640,9 @@
 	if (!(pwd = getpwnam (user_name))) {
 		fprintf (stderr, _("%s: user %s does not exist\n"),
 			 Prog, user_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting user not found", user_name,-1, 0);
+#endif
 		exit (E_NOTFOUND);
 	}
 #ifdef	USE_NIS
@@ -664,8 +726,14 @@
 			fprintf (stderr,
 				 _("%s: error removing directory %s\n"),
 				 Prog, user_home);
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting home directory", user_name,user_id, 1);
+#endif
 			errors++;
 		}
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting home directory", user_name,user_id, 1);
+#endif
 	}
 
 	/*
@@ -690,6 +758,10 @@
 	if (retval == PAM_SUCCESS)
 		pam_end (pamh, PAM_SUCCESS);
 #endif				/* USE_PAM */
+#ifdef WITH_AUDIT
+	if(errors)
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting home directory", user_name,-1, 0);
+#endif
 	exit (errors ? E_HOMEDIR : E_SUCCESS);
 	/* NOT REACHED */
 }
--- shadow/src/Makefile.am.audit	2005-07-07 08:40:27.000000000 +0000
+++ shadow/src/Makefile.am	2005-09-05 13:38:05.000000000 +0000
@@ -51,28 +51,28 @@
 AM_CPPFLAGS    = -DLOCALEDIR=\"$(datadir)/locale\"
 
 chpasswd_LDADD = $(LDADD) $(LIBPAM)
-chage_LDADD    = $(LDADD) $(LIBPAM)
+chage_LDADD    = $(LDADD) $(LIBPAM) $(AUDIT)
 chfn_LDADD     = $(LDADD) $(LIBPAM)
 chsh_SOURCES   = \
 	chsh.c \
 	chsh_chkshell.c
 chsh_LDADD     = $(LDADD) $(LIBPAM)
-groupadd_LDADD = $(LDADD) $(LIBPAM)
-groupdel_LDADD = $(LDADD) $(LIBPAM)
-groupmod_LDADD = $(LDADD) $(LIBPAM)
+groupadd_LDADD = $(LDADD) $(LIBPAM) $(AUDIT)
+groupdel_LDADD = $(LDADD) $(LIBPAM) $(AUDIT)
+groupmod_LDADD = $(LDADD) $(LIBPAM) $(AUDIT)
 login_SOURCES  = \
 	login.c \
 	login_nopam.c
 login_LDADD    = $(LDADD) $(LIBPAM)
 newusers_LDADD = $(LDADD) $(LIBPAM)
-passwd_LDADD   = $(LDADD) $(LIBPAM) $(LIBCRACK)
+passwd_LDADD   = $(LDADD) $(LIBPAM) $(LIBCRACK) $(AUDIT)
 su_SOURCES     = \
 	su.c \
 	suauth.c
 su_LDADD       = $(LDADD) $(LIBPAM)
-useradd_LDADD  = $(LDADD) $(LIBPAM)
-userdel_LDADD  = $(LDADD) $(LIBPAM)
-usermod_LDADD  = $(LDADD) $(LIBPAM)
+useradd_LDADD  = $(LDADD) $(LIBPAM) $(AUDIT)
+userdel_LDADD  = $(LDADD) $(LIBPAM) $(AUDIT)
+usermod_LDADD  = $(LDADD) $(LIBPAM) $(AUDIT)
 
 install-am: all-am
 	$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--- shadow/src/chage.c.audit	2005-09-02 20:18:18.000000000 +0000
+++ shadow/src/chage.c	2005-09-05 13:38:05.000000000 +0000
@@ -366,6 +366,9 @@
 	int retval;
 #endif
 
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
 	sanitize_env ();
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -471,6 +474,9 @@
 
 	if (!amroot && !lflg) {
 		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", NULL,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 
@@ -559,6 +565,9 @@
 		cleanup (1);
 		SYSLOG ((LOG_ERR, "failed locking %s", SHADOW_FILE));
 		closelog ();
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", name,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 	if (!spw_open (locks ? O_RDWR : O_RDONLY)) {
@@ -567,12 +576,18 @@
 		cleanup (2);
 		SYSLOG ((LOG_ERR, "failed opening %s", SHADOW_FILE));
 		closelog ();
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", name,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 
 	if (lflg && (setgid (getgid ()) || setuid (ruid))) {
 		fprintf (stderr, _("%s: failed to drop privileges (%s)\n"),
 			 Prog, strerror (errno));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", name,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 
@@ -598,6 +613,34 @@
 			inactdays = spwd.sp_inact;
 		if (!Eflg)
 			expdays = spwd.sp_expire;
+#ifdef WITH_AUDIT
+                if (Mflg)
+
+		       audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change max age", pw->pw_name,pw->pw_uid, 1);
+                if (mflg)
+		       audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change min age", pw->pw_name,pw->pw_uid, 1);
+                if (dflg)
+                {
+                	char new_lastchg[200];
+	                char old_lastchg[200];
+        	        date_to_str(new_lastchg, sizeof new_lastchg, lastday * DAY);
+                	date_to_str(old_lastchg, sizeof old_lastchg, spwd.sp_lstchg * DAY);
+
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change last change date", pw->pw_name,pw->pw_uid, 1);
+                }
+                if (Wflg)
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change passwd warning", pw->pw_name,pw->pw_uid, 1);
+                if (Iflg)
+		       audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change inactive days", pw->pw_name,pw->pw_uid, 1);
+        	if (Eflg)
+	        {
+        		char new_exp[200];
+                	char old_exp[200];
+	                date_to_str(new_exp, sizeof new_exp, expdays * DAY);
+        	        date_to_str(old_exp, sizeof old_exp, spwd.sp_expire * DAY);
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change passwd expiration", pw->pw_name,pw->pw_uid, 1);
+	        }
+#endif
 	}
 
 	/*
@@ -607,10 +650,16 @@
 
 	if (lflg) {
 		if (!amroot && (ruid != pwent.pw_uid)) {
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", pw->pw_name,pw->pw_uid, 0);
+#endif
 			fprintf (stderr, _("%s: Permission denied.\n"), Prog);
 			closelog ();
 			exit (E_NOPERM);
 		}
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"display aging info", pw->pw_name,pw->pw_uid, 1);
+#endif
 		list_fields ();
 		cleanup (2);
 		closelog ();
@@ -629,8 +678,15 @@
 				 Prog);
 			cleanup (2);
 			closelog ();
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", pw->pw_name,getuid(), 0);
+#endif
 			exit (E_NOPERM);
 		}
+#ifdef WITH_AUDIT
+		else
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change all aging information", pw->pw_name,getuid(), 1);
+#endif
 	}
 	/*
 	 * There was no shadow entry. The new entry will have the encrypted
@@ -653,6 +709,9 @@
 			cleanup (2);
 			SYSLOG ((LOG_ERR, "failed updating %s", PASSWD_FILE));
 			closelog ();
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", pw->pw_name,getuid(), 0);
+#endif
 			exit (E_NOPERM);
 		}
 	}
@@ -676,6 +735,9 @@
 		cleanup (2);
 		SYSLOG ((LOG_ERR, "failed updating %s", SHADOW_FILE));
 		closelog ();
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", pw->pw_name,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 
@@ -689,6 +751,9 @@
 		cleanup (2);
 		SYSLOG ((LOG_ERR, "failed rewriting %s", SHADOW_FILE));
 		closelog ();
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", pw->pw_name,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 #ifdef USE_PAM
@@ -733,6 +798,9 @@
 		cleanup (2);
 		SYSLOG ((LOG_ERR, "failed rewriting %s", PASSWD_FILE));
 		closelog ();
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"change age", pw->pw_name,getuid(), 0);
+#endif
 		exit (E_NOPERM);
 	}
 	cleanup (2);
--- shadow/src/groupmod.c.audit	2005-08-31 17:25:00.000000000 +0000
+++ shadow/src/groupmod.c	2005-09-05 13:38:05.000000000 +0000
@@ -157,6 +157,9 @@
 		fprintf (stderr,
 			 _("%s: %s not found in /etc/group\n"),
 			 Prog, group_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group_name,-1,0);
+#endif
 		exit (E_GRP_UPDATE);
 	}
 	grp = *ogrp;
@@ -174,10 +177,16 @@
 
 	if (!gr_update (&grp)) {
 		fprintf (stderr, _("%s: error adding new group entry\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding group", group_name,-1,0);
+#endif
 		exit (E_GRP_UPDATE);
 	}
 	if (nflg && !gr_remove (group_name)) {
 		fprintf (stderr, _("%s: error removing group entry\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", group_name,-1,0);
+#endif
 		exit (E_GRP_UPDATE);
 	}
 #ifdef	SHADOWGRP
@@ -196,15 +205,24 @@
 
 	if (!sgr_update (&sgrp)) {
 		fprintf (stderr, _("%s: error adding new group entry\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding group", group_name,-1,0);
+#endif
 		exit (E_GRP_UPDATE);
 	}
 	if (nflg && !sgr_remove (group_name)) {
 		fprintf (stderr, _("%s: error removing group entry\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group", group_name,-1,0);
+#endif
 		exit (E_GRP_UPDATE);
 	}
       out:
 #endif				/* SHADOWGRP */
 
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifing group", group_name, group_id,1);
+#endif
 	if (nflg)
 		SYSLOG ((LOG_INFO, "change group `%s' to `%s'",
 			 group_name, group_newname));
@@ -241,6 +259,9 @@
 	 */
 
 	fprintf (stderr, _("%s: %u is not a unique GID\n"), Prog, group_newid);
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modify gid", NULL,group_newid,0);
+#endif
 	exit (E_GID_IN_USE);
 }
 
@@ -272,6 +293,9 @@
 			fprintf (stderr,
 				 _("%s: %s is not a unique name\n"), Prog,
 				 group_newname);
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group_name,-1,0);
+#endif
 			exit (E_NAME_IN_USE);
 		}
 		return;
@@ -283,6 +307,9 @@
 
 	fprintf (stderr, _("%s: %s is not a valid group name\n"),
 		 Prog, group_newname);
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group_name,-1,0);
+#endif
 	exit (E_BAD_ARG);
 }
 
@@ -308,6 +335,9 @@
 				fprintf (stderr,
 					 _("%s: invalid group %s\n"),
 					 Prog, optarg);
+#ifdef WITH_AUDIT
+				audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", NULL,group_newid,0);
+#endif
 				exit (E_BAD_ARG);
 			}
 			break;
@@ -416,6 +446,10 @@
 	int retval;
 #endif
 
+#ifdef WITH_AUDIT
+	audit_help_open();	
+#endif
+
 	/*
 	 * Get my name so that I can use it to report errors.
 	 */
@@ -471,10 +505,21 @@
 	if (!(grp = getgrnam (group_name))) {
 		fprintf (stderr, _("%s: group %s does not exist\n"),
 			 Prog, group_name);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group_name,-1,0);
+#endif
 		exit (E_NOTFOUND);
 	} else
 		group_id = grp->gr_gid;
 
+#ifdef WITH_AUDIT
+	/* Set new name/id to original if not specified on command line */
+	if (nflg == 0)
+	        group_newname = group_name;
+	if (gflg == 0)
+        	group_newid = group_id;
+#endif
+
 #ifdef	USE_NIS
 	/*
 	 * Now make sure it isn't an NIS group.
@@ -486,6 +531,9 @@
 		fprintf (stderr, _("%s: group %s is a NIS group\n"),
 			 Prog, group_name);
 
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group_name,-1,0);
+#endif
 		if (!yp_get_default_domain (&nis_domain) &&
 		    !yp_master (nis_domain, "group.byname", &nis_master)) {
 			fprintf (stderr, _("%s: %s is the NIS master\n"),
--- shadow/src/usermod.c.audit	2005-08-31 17:25:00.000000000 +0000
+++ shadow/src/usermod.c	2005-09-05 13:38:05.000000000 +0000
@@ -87,12 +87,16 @@
 static gid_t user_gid;
 static gid_t user_newgid;
 static char *user_comment;
+static char *user_newcomment;  /* Audit */
 static char *user_home;
 static char *user_newhome;
 static char *user_shell;
+static char *user_newshell;    /* Audit */
 
 static long user_expire;
+static long user_newexpire;    /* Audit */
 static long user_inactive;
+static long user_newinactive;  /* Audit */
 static long sys_ngroups;
 static char **user_groups;	/* NULL-terminated list */
 
@@ -298,6 +302,9 @@
 	if (Lflg && pw_pass[0] != '!') {
 		char *buf = xmalloc (strlen (pw_pass) + 2);
 
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"updating passwd", user_newname,user_newid,0);
+#endif
 		SYSLOG ((LOG_INFO, "lock user `%s' password", pw_name));
 		strcpy (buf, "!");
 		strcat (buf, pw_pass);
@@ -305,6 +312,9 @@
 	} else if (Uflg && pw_pass[0] == '!') {
 		char *s;
 
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"updating password", user_newname,user_newid,0);
+#endif
 		SYSLOG ((LOG_INFO, "unlock user `%s' password", pw_name));
 		s = pw_pass;
 		while (*s) {
@@ -312,6 +322,9 @@
 			s++;
 		}
 	} else if (pflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing password", user_newname,user_newid,1);
+#endif
 		SYSLOG ((LOG_INFO, "change user `%s' password", pw_name));
 		pw_pass = xstrdup (user_pass);
 	}
@@ -328,6 +341,9 @@
 static void new_pwent (struct passwd *pwent)
 {
 	if (lflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing name", user_newname,user_newid,1);
+#endif
 		SYSLOG ((LOG_INFO, "change user name `%s' to `%s'",
 			 pwent->pw_name, user_newname));
 		pwent->pw_name = xstrdup (user_newname);
@@ -337,31 +353,54 @@
 		    new_pw_passwd (pwent->pw_passwd, pwent->pw_name);
 
 	if (uflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing uid", user_newname,user_newid,1);
+#endif
 		SYSLOG ((LOG_INFO,
 			 "change user `%s' UID from `%d' to `%d'",
 			 pwent->pw_name, pwent->pw_uid, user_newid));
 		pwent->pw_uid = user_newid;
 	}
 	if (gflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing primary group", user_newname,user_newid,1);
+#endif
 		SYSLOG ((LOG_INFO,
 			 "change user `%s' GID from `%d' to `%d'",
 			 pwent->pw_name, pwent->pw_gid, user_newgid));
 		pwent->pw_gid = user_newgid;
 	}
-	if (cflg)
+	if (cflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing comment", user_newname,user_newid,1);
+                pwent->pw_gecos = user_newcomment;
+#else
 		pwent->pw_gecos = user_comment;
+#endif
+	}
 
 	if (dflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing home directory", user_newname,user_newid,1);
+#endif
 		SYSLOG ((LOG_INFO,
 			 "change user `%s' home from `%s' to `%s'",
 			 pwent->pw_name, pwent->pw_dir, user_newhome));
 		pwent->pw_dir = user_newhome;
 	}
 	if (sflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing user shell", user_newname,user_newid,1);
+                SYSLOG ((LOG_INFO,
+                         "change user `%s' shell from `%s' to `%s'",
+                         pwent->pw_name, pwent->pw_shell, user_newshell));
+                pwent->pw_shell = user_newshell;
+#else		
 		SYSLOG ((LOG_INFO,
 			 "change user `%s' shell from `%s' to `%s'",
 			 pwent->pw_name, pwent->pw_shell, user_shell));
 		pwent->pw_shell = user_shell;
+#endif
 	}
 }
 
@@ -378,17 +417,69 @@
 		spent->sp_namp = xstrdup (user_newname);
 
 	if (fflg) {
+#ifdef WITH_AUDIT
+	       audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing inactive days", user_newname,user_newid,1);
+               SYSLOG ((LOG_INFO,
+                        "change user `%s' inactive from `%ld' to `%ld'",
+                        spent->sp_namp, spent->sp_inact, user_newinactive));
+               spent->sp_inact = user_newinactive;
+#else
+
 		SYSLOG ((LOG_INFO,
 			 "change user `%s' inactive from `%ld' to `%ld'",
 			 spent->sp_namp, spent->sp_inact, user_inactive));
 		spent->sp_inact = user_inactive;
+#endif
 	}
 	if (eflg) {
 		/* XXX - dates might be better than numbers of days.  --marekm */
+#ifdef WITH_AUDIT
+                if(audit_fd >= 0)
+                {
+                	time_t exp_t;
+                        struct tm *exp_tm;
+                        char new_exp[16], old_exp[16];
+
+                        if (user_newexpire == -1)
+                        	new_exp[0] = '\0';
+                        else {
+                                exp_t = user_newexpire * DAY;
+                                exp_tm = gmtime(&exp_t);
+#ifdef HAVE_STRFTIME
+                                strftime(new_exp, sizeof(new_exp), "%Y-%m-%d", exp_tm);
+#else
+                                memset(new_exp, 0, sizeof(new_exp));
+                                snprintf(new_exp, sizeof(new_exp)-1, "%04i-%02i-%02i",
+          	                      exp_tm->tm_year + 1900, exp_tm->tm_mon + 1, exp_tm->tm_mday);
+#endif
+                        }
+
+                        if (user_expire == -1)
+                                old_exp[0] = '\0';
+                        else {
+                                exp_t = user_expire * DAY;
+                                exp_tm = gmtime(&exp_t);
+#ifdef HAVE_STRFTIME
+                                strftime(old_exp, sizeof(old_exp), "%Y-%m-%d", exp_tm);
+#else
+                                memset(old_exp, 0, sizeof(old_exp));
+                                snprintf(old_exp, sizeof(old_exp)-1, "%04i-%02i-%02i",
+                                	exp_tm->tm_year + 1900, exp_tm->tm_mon + 1, exp_tm->tm_mday);
+#endif
+                        }
+		        audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing expiration date", user_newname,user_newid,1);
+		}
+
+                SYSLOG ((LOG_INFO,
+ 		                         "change user `%s' expiration from `%ld' to `%ld'",
+                         spent->sp_namp, spent->sp_expire, user_newexpire));
+                spent->sp_expire = user_newexpire;
+#else
 		SYSLOG ((LOG_INFO,
 			 "change user `%s' expiration from `%ld' to `%ld'",
 			 spent->sp_namp, spent->sp_expire, user_expire));
 		spent->sp_expire = user_expire;
+#endif
 	}
 	spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp, spent->sp_namp);
 	if (pflg)
@@ -409,6 +500,9 @@
 	if (is_shadow_pwd)
 		spw_unlock ();
 	(void) pw_unlock ();
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying account", user_name,-1,0);
+#endif
 	exit (code);
 }
 
@@ -471,6 +565,9 @@
 				ngrp->gr_mem = add_list (ngrp->gr_mem,
 							 user_newname);
 				changed = 1;
+#ifdef WITH_AUDIT
+				audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing group member", user_newname,-1,1);
+#endif
 				SYSLOG ((LOG_INFO,
 					 "change `%s' to `%s' in group `%s'",
 					 user_name, user_newname,
@@ -479,6 +576,9 @@
 		} else if (was_member && !aflg && Gflg && !is_member) {
 			ngrp->gr_mem = del_list (ngrp->gr_mem, user_name);
 			changed = 1;
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"removing group member", user_name,-1,1);
+#endif
 			SYSLOG ((LOG_INFO, "delete `%s' from group `%s'",
 				 user_name, ngrp->gr_name));
 		} else if (!was_member && Gflg && is_member) {
@@ -486,6 +586,9 @@
 						 lflg ? user_newname :
 						 user_name);
 			changed = 1;
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user to group", user_name,-1,1);
+#endif
 			SYSLOG ((LOG_INFO, "add `%s' to group `%s'",
 				 lflg ? user_newname : user_name,
 				 ngrp->gr_name));
@@ -577,6 +680,9 @@
 			nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name);
 			nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname);
 			changed = 1;
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing admin name in shadow group", user_name,-1, 1);
+#endif
 			SYSLOG ((LOG_INFO,
 				 "change admin `%s' to `%s' in shadow group `%s'",
 				 user_name, user_newname, nsgrp->sg_name));
@@ -588,6 +694,9 @@
 				nsgrp->sg_mem = add_list (nsgrp->sg_mem,
 							  user_newname);
 				changed = 1;
+#ifdef WITH_AUDIT
+				audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing member in shadow group", user_name,-1, 1);
+#endif
 				SYSLOG ((LOG_INFO,
 					 "change `%s' to `%s' in shadow group `%s'",
 					 user_name, user_newname,
@@ -596,6 +705,9 @@
 		} else if (was_member && !aflg && Gflg && !is_member) {
 			nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name);
 			changed = 1;
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"removing user from shadow group", user_name,-1, 1);
+#endif
 			SYSLOG ((LOG_INFO,
 				 "delete `%s' from shadow group `%s'",
 				 user_name, nsgrp->sg_name));
@@ -604,6 +716,9 @@
 						  lflg ? user_newname :
 						  user_name);
 			changed = 1;
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding user to shadow group", user_newname,-1, 1);
+#endif
 			SYSLOG ((LOG_INFO, "add `%s' to shadow group `%s'",
 				 lflg ? user_newname : user_name,
 				 nsgrp->sg_name));
@@ -707,6 +822,9 @@
 		exit (E_NOTFOUND);
 	}
 	user_name = argv[argc - 1];
+#ifdef WITH_AUDIT
+	user_newname = user_name;
+#endif
 
 #ifdef	USE_NIS
 
@@ -730,14 +848,35 @@
 	}
 #endif
 	user_id = pwd->pw_uid;
+#ifdef WITH_AUDIT
+        user_newid = user_id;
+#endif
 	user_gid = pwd->pw_gid;
+#ifdef WITH_AUDIT
+	user_newgid = user_gid;
+#endif
 	user_comment = xstrdup (pwd->pw_gecos);
+#ifdef WITH_AUDIT
+        user_newcomment = user_comment;
+#endif
 	user_home = xstrdup (pwd->pw_dir);
+#ifdef WITH_AUDIT
+        user_newhome = user_home;
+#endif
 	user_shell = xstrdup (pwd->pw_shell);
+#ifdef WITH_AUDIT
+        user_newshell = user_shell;
+#endif
 
 	if (is_shadow_pwd && (spwd = getspnam (user_name))) {
 		user_expire = spwd->sp_expire;
+#ifdef WITH_AUDIT
+                user_newexpire = user_expire;
+#endif
 		user_inactive = spwd->sp_inact;
+#ifdef WITH_AUDIT
+                user_newinactive = user_inactive;
+#endif
 	}
 
 	while ((arg = getopt (argc, argv, "ac:d:e:f:g:G:l:Lmop:s:u:U")) != EOF) {
@@ -752,7 +891,12 @@
 					 Prog, optarg);
 				exit (E_BAD_ARG);
 			}
+#ifdef WITH_AUDIT
+                        user_newcomment = optarg;
+#else
+
 			user_comment = optarg;
+#endif
 			cflg++;
 			break;
 		case 'd':
@@ -767,21 +911,40 @@
 			break;
 		case 'e':
 			if (*optarg) {
+#ifdef WITH_AUDIT
+                                user_newexpire = strtoday (optarg);
+                                if (user_newexpire == -1) {
+#else
 				user_expire = strtoday (optarg);
 				if (user_expire == -1) {
+#endif
 					fprintf (stderr,
 						 _
 						 ("%s: invalid date `%s'\n"),
 						 Prog, optarg);
 					exit (E_BAD_ARG);
 				}
+#ifdef WITH_AUDIT
+                                user_newexpire *= DAY / SCALE;
+#else
+
 				user_expire *= DAY / SCALE;
+#endif
 			} else
+#ifdef WITH_AUDIT
+                                user_newexpire = -1;
+#else
+
 				user_expire = -1;
+#endif
 			eflg++;
 			break;
 		case 'f':
+#ifdef WITH_AUDIT
+                        user_newinactive = get_number (optarg);
+#else
 			user_inactive = get_number (optarg);
+#endif
 			fflg++;
 			break;
 		case 'g':
@@ -851,7 +1014,11 @@
 					 Prog, optarg);
 				exit (E_BAD_ARG);
 			}
+#ifdef WITH_AUDIT
+                        user_newshell = optarg;
+#else
 			user_shell = optarg;
+#endif
 			sflg++;
 			break;
 		case 'u':
@@ -1091,6 +1258,12 @@
 							 _
 							 ("%s: warning: failed to completely remove old home directory %s"),
 							 Prog, user_home);
+#ifdef WITH_AUDIT
+					audit_logger(AUDIT_USER_CHAUTHTOK,
+						     Prog,
+                                                     "moving home directory", 
+						     user_newname,user_newid, 1);
+#endif
 					return;
 				}
 
@@ -1103,11 +1276,18 @@
 				 Prog, user_home, user_newhome);
 			fail_exit (E_HOMEDIR);
 		}
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"moving home directory", user_newname,user_newid, 1);
+#endif
 	}
-	if (uflg || gflg)
+	if (uflg || gflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing home directory owner", user_newname,user_newid, 1);
+#endif
 		chown (dflg ? user_newhome : user_home,
 		       uflg ? user_newid : user_id,
 		       gflg ? user_newgid : user_gid);
+	}
 }
 
 /*
@@ -1199,16 +1379,30 @@
 		close (fd);
 		return;
 	}
-	if (uflg && fchown (fd, user_newid, (gid_t) - 1) < 0)
-		perror (_("failed to change mailbox owner"));
+	if (uflg) {
+		if  (fchown (fd, user_newid, (gid_t) - 1) < 0) {
+			perror (_("failed to change mailbox owner"));
+		}
+#ifdef WITH_AUDIT
+		else {
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing mail file owner", user_newname,user_newid, 1);
+		}
+#endif
+	}
 
 	close (fd);
 
 	if (lflg) {
 		snprintf (newmailfile, sizeof newmailfile, "%s/%s",
 			  maildir, user_newname);
-		if (link (mailfile, newmailfile) || unlink (mailfile))
+		if (link (mailfile, newmailfile) || unlink (mailfile)) {
 			perror (_("failed to rename mailbox"));
+		}
+#ifdef WITH_AUDIT
+		else {
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing mail file name", user_newname,user_newid, 1);
+		}
+#endif
 	}
 }
 #endif
@@ -1234,6 +1428,10 @@
 	int retval;
 #endif
 
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
+
 	/*
 	 * Get my name so that I can use it to report errors.
 	 */
--- shadow/src/gpasswd.c.audit	2005-08-31 17:25:00.000000000 +0000
+++ shadow/src/gpasswd.c	2005-09-05 13:38:05.000000000 +0000
@@ -57,6 +57,8 @@
 static int
  aflg = 0, Aflg = 0, dflg = 0, Mflg = 0, rflg = 0, Rflg = 0;
 
+unsigned int bywho = -1;
+
 #ifndef	RETRIES
 #define	RETRIES	3
 #endif
@@ -188,6 +190,10 @@
 	char *group = NULL;
 	char *members = NULL;
 
+#ifdef WITH_AUDIT
+	audit_help_open();
+#endif
+
 	sanitize_env ();
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -202,6 +208,7 @@
 	 */
 
 	amroot = getuid () == 0;
+	bywho = getuid();
 	Prog = Basename (argv[0]);
 
 	OPENLOG ("gpasswd");
@@ -219,14 +226,21 @@
 				fprintf (stderr,
 					 _("%s: unknown user %s\n"), Prog,
 					 user);
+#ifdef WITH_AUDIT
+				audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding to group", user,-1, 0);
+#endif
 				exit (1);
 			}
 			aflg++;
 			break;
 #ifdef SHADOWGRP
 		case 'A':
-			if (!amroot)
+			if (!amroot) {
+#ifdef WITH_AUDIT
+				audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"Listing administrators", NULL,bywho, 0);
+#endif
 				failure ();
+			}
 			if (!is_shadowgrp) {
 				fprintf (stderr,
 					 _
@@ -247,8 +261,12 @@
 		case 'g':	/* no-op from normal password */
 			break;
 		case 'M':
-			if (!amroot)
+			if (!amroot) {
+#ifdef WITH_AUDIT
+				audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"listing members", NULL,bywho, 0);
+#endif
 				failure ();
+			}
 			members = optarg;
 			if (check_list (members))
 				exit (1);
@@ -282,6 +300,10 @@
 	pw = get_my_pwent ();
 	if (!pw) {
 		fprintf (stderr, _("Who are you?\n"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"user lookup", NULL, bywho, 0);
+#endif
+                failure();
 		exit (1);
 	}
 	myname = xstrdup (pw->pw_name);
@@ -301,6 +323,10 @@
 
 	if (!(gr = getgrnam (group))) {
 		fprintf (stderr, _("unknown group: %s\n"), group);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"group lookup", group,-1, 0);
+#endif
+                failure();
 		exit (1);
 	}
 	grent = *gr;
@@ -342,8 +368,12 @@
 	 * user can.
 	 */
 
-	if (!amroot && !is_on_list (sgent.sg_adm, myname))
+	if (!amroot && !is_on_list (sgent.sg_adm, myname)) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modify group", group,-1, 0);
+#endif
 		failure ();
+	}
 #else				/* ! SHADOWGRP */
 
 #ifdef FIRST_MEMBER_IS_ADMIN
@@ -356,11 +386,19 @@
 	 */
 
 	if (!amroot) {
-		if (grent.gr_mem[0] == (char *) 0)
+		if (grent.gr_mem[0] == (char *) 0) {
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group,-1, 0);
+#endif
 			failure ();
+		}
 
-		if (strcmp (grent.gr_mem[0], myname) != 0)
+		if (strcmp (grent.gr_mem[0], myname) != 0) {
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", myname,-1, 0);
+#endif
 			failure ();
+		}
 	}
 #else
 	/*
@@ -369,8 +407,12 @@
 	 * be just a normal user.  --marekm
 	 */
 
-	if (!amroot)
+	if (!amroot) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"modifying group", group,-1, 0);
+#endif
 		failure ();
+	}
 #endif
 
 #endif				/* SHADOWGRP */
@@ -385,6 +427,9 @@
 #ifdef	SHADOWGRP
 		sgent.sg_passwd = "";	/* XXX warning: const */
 #endif
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting group password", group,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "remove password from group %s by %s",
 			 group, myname));
 		goto output;
@@ -398,6 +443,9 @@
 #ifdef	SHADOWGRP
 		sgent.sg_passwd = "!";	/* XXX warning: const */
 #endif
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"restrict access to group", group,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "restrict access to group %s by %s",
 			 group, myname));
 		goto output;
@@ -414,6 +462,9 @@
 #ifdef	SHADOWGRP
 		sgent.sg_mem = add_list (sgent.sg_mem, user);
 #endif
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"adding group member", user,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "add member %s to group %s by %s", user,
 			 group, myname));
 		goto output;
@@ -442,8 +493,14 @@
 		if (!removed) {
 			fprintf (stderr, _("%s: unknown member %s\n"),
 				 Prog, user);
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting member", user,-1, 0);
+#endif		
 			exit (1);
 		}
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"deleting member", user,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "remove member %s from group %s by %s",
 			 user, group, myname));
 		goto output;
@@ -456,6 +513,9 @@
 	 */
 
 	if (Aflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"setting group admin", group,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "set administrators of %s to %s",
 			 group, admins));
 		sgent.sg_adm = comma_to_list (admins);
@@ -471,6 +531,9 @@
 	 */
 
 	if (Mflg) {
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"setting group members", group,-1, 1);
+#endif
 		SYSLOG ((LOG_INFO, "set members of %s to %s", group, members));
 #ifdef SHADOWGRP
 		sgent.sg_mem = comma_to_list (members);
@@ -487,6 +550,9 @@
 
 	if (!isatty (0) || !isatty (1)) {
 		fprintf (stderr, _("%s: Not a tty\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing password", group,-1, 0);
+#endif
 		exit (1);
 	}
 
@@ -526,8 +592,12 @@
 		strzero (cp);
 		memzero (pass, sizeof pass);
 
-		if (retries + 1 < RETRIES)
+		if (retries + 1 < RETRIES) {
 			puts (_("They don't match; try again"));
+#ifdef WITH_AUDIT
+			audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing password", group,-1, 0);
+#endif
+		}
 	}
 
 	if (retries == RETRIES) {
@@ -543,6 +613,9 @@
 	else
 #endif
 		grent.gr_passwd = cp;
+#ifdef WITH_AUDIT
+	audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing password", group,-1, 1);
+#endif
 	SYSLOG ((LOG_INFO, "change the password for group %s by %s", group,
 		 myname));
 
@@ -557,6 +630,9 @@
 	if (setuid (0)) {
 		fprintf (stderr, _("Cannot change ID to root.\n"));
 		SYSLOG ((LOG_ERR, "can't setuid(0)"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"changing id to root", group,-1, 0);
+#endif
 		closelog ();
 		exit (1);
 	}
@@ -565,48 +641,72 @@
 	if (!gr_lock ()) {
 		fprintf (stderr, _("%s: can't get lock\n"), Prog);
 		SYSLOG ((LOG_WARN, "failed to get lock for /etc/group"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking /etc/group", group,-1, 0);
+#endif
 		exit (1);
 	}
 #ifdef	SHADOWGRP
 	if (is_shadowgrp && !sgr_lock ()) {
 		fprintf (stderr, _("%s: can't get shadow lock\n"), Prog);
 		SYSLOG ((LOG_WARN, "failed to get lock for /etc/gshadow"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"locking /etc/gshadow", group,-1, 0);
+#endif
 		exit (1);
 	}
 #endif
 	if (!gr_open (O_RDWR)) {
 		fprintf (stderr, _("%s: can't open file\n"), Prog);
 		SYSLOG ((LOG_WARN, "cannot open /etc/group"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening /etc/group", group,-1, 0);
+#endif
 		exit (1);
 	}
 #ifdef	SHADOWGRP
 	if (is_shadowgrp && !sgr_open (O_RDWR)) {
 		fprintf (stderr, _("%s: can't open shadow file\n"), Prog);
 		SYSLOG ((LOG_WARN, "cannot open /etc/gshadow"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"opening /etc/gshadow", group,-1, 0);
+#endif
 		exit (1);
 	}
 #endif
 	if (!gr_update (&grent)) {
 		fprintf (stderr, _("%s: can't update entry\n"), Prog);
 		SYSLOG ((LOG_WARN, "cannot update /etc/group"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"updating /etc/group", group,-1, 0);
+#endif
 		exit (1);
 	}
 #ifdef	SHADOWGRP
 	if (is_shadowgrp && !sgr_update (&sgent)) {
 		fprintf (stderr, _("%s: can't update shadow entry\n"), Prog);
 		SYSLOG ((LOG_WARN, "cannot update /etc/gshadow"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"updating /etc/gshadow", group,-1, 0);
+#endif
 		exit (1);
 	}
 #endif
 	if (!gr_close ()) {
 		fprintf (stderr, _("%s: can't re-write file\n"), Prog);
 		SYSLOG ((LOG_WARN, "cannot re-write /etc/group"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"rewriting /etc/group", group,-1, 0);
+#endif
 		exit (1);
 	}
 #ifdef	SHADOWGRP
 	if (is_shadowgrp && !sgr_close ()) {
 		fprintf (stderr, _("%s: can't re-write shadow file\n"), Prog);
 		SYSLOG ((LOG_WARN, "cannot re-write /etc/gshadow"));
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"rewriting /etc/gshadow", group,-1, 0);
+#endif
 		exit (1);
 	}
 	if (is_shadowgrp)
@@ -614,6 +714,9 @@
 #endif
 	if (!gr_unlock ()) {
 		fprintf (stderr, _("%s: can't unlock file\n"), Prog);
+#ifdef WITH_AUDIT
+		audit_logger(AUDIT_USER_CHAUTHTOK,Prog,"unlocking group file", group,-1, 0);
+#endif
 		exit (1);
 	}