Blob Blame Raw
--- gdm-2.17.6/configure.ac.audit-login	2007-01-30 16:21:18.000000000 -0500
+++ gdm-2.17.6/configure.ac	2007-02-07 22:27:55.000000000 -0500
@@ -825,6 +825,10 @@
 AC_SUBST(logdir, ${localstatedir}/log/gdm)
 AC_SUBST(pixmapdir, ${datadir}/pixmaps)
 
+AC_ARG_WITH(libaudit,
+  [  --with-libaudit=[auto/yes/no]  Add Linux audit support [default=auto]],,
+  with_libaudit=auto)
+
 withval=""
 AC_ARG_WITH(at-bindir,
 [  --with-at-bindir=<PATH>   PATH to Accessible Technology programs [default=BINDIR]],)
@@ -936,6 +940,24 @@
    AC_MSG_RESULT(no)
 fi
 
+# Check for Linux auditing API
+#
+# libaudit detection
+if test x$with_libaudit = xno ; then
+    have_libaudit=no;
+else
+    # See if we have audit daemon library
+    AC_CHECK_LIB(audit, audit_log_user_message,
+                 have_libaudit=yes, have_libaudit=no)
+fi
+
+AM_CONDITIONAL(HAVE_LIBAUDIT, test x$have_libaudit = xyes)
+
+if test x$have_libaudit = xyes ; then
+    EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -laudit"
+    AC_DEFINE(HAVE_LIBAUDIT,1,[linux audit support])
+fi
+
 # Check for Solaris auditing API
 # Note, Solaris auditing not supported for Solaris 9 or earlier and
 # should not be used on these versions of Solaris if auditing is
--- gdm-2.17.6/daemon/verify-pam.c.audit-login	2007-02-07 22:05:17.000000000 -0500
+++ gdm-2.17.6/daemon/verify-pam.c	2007-02-07 22:30:55.000000000 -0500
@@ -47,6 +47,14 @@
 #include <bsm/adt_event.h>
 #endif	/* HAVE_ADT */
 
+#define  AU_FAILED 0
+#define  AU_SUCCESS 1
+#ifdef HAVE_LIBAUDIT
+#include <libaudit.h>
+#else
+#define log_to_audit_system(l,h,d,s)	do { ; } while (0)
+#endif
+
 /* Evil, but this way these things are passed to the child session */
 static pam_handle_t *pamh = NULL;
 
@@ -784,6 +792,53 @@
 	return TRUE;
 }
 
+/**
+ * log_to_audit_system:
+ * @login: Name of user
+ * @hostname: Name of host machine
+ * @tty: Name of display 
+ * @success: 1 for success, 0 for failure
+ *
+ * Logs the success or failure of the login attempt with the linux kernel
+ * audit system. The intent is to capture failed events where the user
+ * fails authentication or otherwise is not permitted to login. There are
+ * many other places where pam could potentially fail and cause login to 
+ * fail, but these are system failures rather than the signs of an account
+ * being hacked.
+ *
+ * Returns nothing.
+ */
+
+#ifdef HAVE_LIBAUDIT
+static void 
+log_to_audit_system(const char *login,
+		const char *hostname,
+		const char *tty,
+		gboolean success)
+{
+	struct passwd *pw;
+	char buf[64];
+	int audit_fd;
+
+	audit_fd = audit_open();
+	if (login)
+		pw = getpwnam(login);
+	else {
+		login = "unknown";
+		pw = NULL;
+	}
+	if (pw) {
+		snprintf(buf, sizeof(buf), "uid=%d", pw->pw_uid);
+		audit_log_user_message(audit_fd, AUDIT_USER_LOGIN,
+			buf, hostname, NULL, tty, (int)success);
+	} else {
+		snprintf(buf, sizeof(buf), "acct=%s", login);
+		audit_log_user_message(audit_fd, AUDIT_USER_LOGIN,
+			buf, hostname, NULL, tty, (int)success);
+	}
+	close(audit_fd);
+}
+#endif
 
 /**
  * gdm_verify_user:
@@ -903,6 +958,9 @@
     /* Start authentication session */
     did_we_ask_for_password = FALSE;
     if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) {
+	    /* Log the failed login attempt */
+	    log_to_audit_system(login, d->hostname, display, AU_FAILED);
+
 	    if ( ! ve_string_empty (selected_user)) {
 		    pam_handle_t *tmp_pamh;
 
@@ -1024,6 +1082,8 @@
 	  ( ! gdm_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) &&
 	pwent != NULL &&
 	pwent->pw_uid == 0) {
+	    /* Log the failed login attempt */
+	    log_to_audit_system(login, d->hostname, display, AU_FAILED);
 	    gdm_error (_("Root login disallowed on display '%s'"),
 		       display);
 	    gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX,
@@ -1057,6 +1117,8 @@
 	break;
     case PAM_NEW_AUTHTOK_REQD :
 	if ((pamerr = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) {
+	    /* Log the failed login attempt */
+	    log_to_audit_system(login, d->hostname, display, AU_FAILED);
 	    gdm_error (_("Authentication token change failed for user %s"), login);
 	    gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, 
 		    _("\nThe change of the authentication token failed. "
@@ -1074,18 +1136,24 @@
 #endif	/* HAVE_ADT */
         break;
     case PAM_ACCT_EXPIRED :
+	/* Log the failed login attempt */
+	log_to_audit_system(login, d->hostname, display, AU_FAILED);
 	gdm_error (_("User %s no longer permitted to access the system"), login);
 	gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, 
 		_("\nThe system administrator has disabled your account."));
 	error_msg_given = TRUE;
 	goto pamerr;
     case PAM_PERM_DENIED :
+	/* Log the failed login attempt */
+	log_to_audit_system(login, d->hostname, display, AU_FAILED);
 	gdm_error (_("User %s not permitted to gain access at this time"), login);
 	gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, 
 		_("\nThe system administrator has disabled access to the system temporarily."));
 	error_msg_given = TRUE;
 	goto pamerr;
     default :
+	/* Log the failed login attempt */
+	log_to_audit_system(login, d->hostname, display, AU_FAILED);
 	if (gdm_slave_action_pending ())
 	    gdm_error (_("Couldn't set acct. mgmt for %s"), login);
 	goto pamerr;
@@ -1137,6 +1205,8 @@
 		    gdm_error (_("Couldn't open session for %s"), login);
 	    goto pamerr;
     }
+    /* Login succeeded */
+    log_to_audit_system(login, d->hostname, display, AU_SUCCESS);
 
     /* Workaround to avoid gdm messages being logged as PAM_pwdb */
     closelog ();