diff -rup audit-1.7.18/audisp/plugins/prelude/audisp-prelude.c audit-1.7.18-ba/audisp/plugins/prelude/audisp-prelude.c
--- audit-1.7.18/audisp/plugins/prelude/audisp-prelude.c	2010-09-19 21:55:07.000000000 +0200
+++ audit-1.7.18-ba/audisp/plugins/prelude/audisp-prelude.c	2011-04-28 10:45:20.000000000 +0200
@@ -44,7 +44,7 @@
 typedef enum { AS_LOGIN, AS_MAX_LOGIN_FAIL, AS_MAX_LOGIN_SESS, AS_ABEND,
 	AS_PROM, AS_MAC_STAT, AS_LOGIN_LOCATION, AS_LOGIN_TIME, AS_MAC,
 	AS_AUTH, AS_WATCHED_LOGIN, AS_WATCHED_FILE, AS_WATCHED_EXEC, AS_MK_EXE,
-	AS_MMAP0, AS_WATCHED_SYSCALL, AS_TOTAL } as_description_t;
+	AS_MMAP0, AS_WATCHED_SYSCALL, AS_TTY, AS_TOTAL } as_description_t;
 const char *assessment_description[AS_TOTAL] = {
  "A user has attempted to login",
  "The maximum allowed login failures for this account has been reached. This could be an attempt to gain access to the account by someone other than the real account holder.",
@@ -61,7 +61,8 @@ const char *assessment_description[AS_TO
  "A user has attempted to execute a program that is being watched.",
  "A user has attempted to create an executable program",
  "A program has attempted mmap a fixed memory page at an address sometimes used as part of a kernel exploit",
- "A user has run a command that issued a watched syscall"
+ "A user has run a command that issued a watched syscall",
+ "A user has entered keystrokes on a terminal"
 };
 typedef enum { M_NORMAL, M_TEST } output_t;
 typedef enum { W_NO, W_FILE, W_EXEC, W_MK_EXE } watched_t;
@@ -1981,6 +1982,83 @@ static void handle_watched_syscalls(aupa
 	}
 }
 
+static int tty_alert(auparse_state_t *au, idmef_message_t *idmef,
+		idmef_alert_t *alert)
+{
+	int ret;
+
+	idmef_source_t *source;
+	idmef_user_t *suser;
+	idmef_user_id_t *user_id;
+	idmef_impact_type_t impact_type;
+    idmef_assessment_t *assessment;
+	idmef_impact_t *impact;
+	idmef_impact_severity_t severity;
+	prelude_string_t *str;
+	idmef_impact_completion_t completion = IDMEF_IMPACT_COMPLETION_ERROR;
+
+	/* Fill in information about the event's source */
+	ret = idmef_alert_new_source(alert, &source, -1);
+	PRELUDE_FAIL_CHECK;
+
+	ret = idmef_source_new_user(source, &suser);
+	PRELUDE_FAIL_CHECK;
+	idmef_user_set_category(suser, IDMEF_USER_CATEGORY_APPLICATION);
+	ret = idmef_user_new_user_id(suser, &user_id, 0);	
+	PRELUDE_FAIL_CHECK;
+	idmef_user_id_set_type(user_id, IDMEF_USER_ID_TYPE_ORIGINAL_USER);
+	ret = get_loginuid_info(au, user_id);
+	PRELUDE_FAIL_CHECK;
+
+	ret = get_tty_info(au, user_id);
+	PRELUDE_FAIL_CHECK;
+
+	ret = get_comm_info(au, source, NULL);
+	PRELUDE_FAIL_CHECK;
+
+	ret = add_execve_data(au, alert);
+	PRELUDE_FAIL_CHECK;
+
+	ret = add_serial_number_data(au, alert);
+	PRELUDE_FAIL_CHECK;
+
+	/* Describe event */
+	ret = set_classification(alert, "Keylogger");
+	PRELUDE_FAIL_CHECK;
+
+	/* Assess impact */
+	if (get_loginuid(au) == 0)
+		impact_type = IDMEF_IMPACT_TYPE_ADMIN;
+	else
+		impact_type = IDMEF_IMPACT_TYPE_USER;
+	// Adjust the rating on AVC's based on if they succeeded or not
+	completion = IDMEF_IMPACT_COMPLETION_SUCCEEDED;
+	severity = IDMEF_IMPACT_SEVERITY_LOW;
+	
+	ret = idmef_alert_new_assessment(alert, &assessment);
+	PRELUDE_FAIL_CHECK;
+	ret = idmef_assessment_new_impact(assessment, &impact);
+	PRELUDE_FAIL_CHECK;
+	idmef_impact_set_severity(impact, severity);
+	PRELUDE_FAIL_CHECK;
+	idmef_impact_set_type(impact, impact_type);
+	PRELUDE_FAIL_CHECK;
+	ret = idmef_impact_new_description(impact, &str);
+	PRELUDE_FAIL_CHECK;
+	prelude_string_set_ref(str, assessment_description[AS_WATCHED_EXEC]);
+	PRELUDE_FAIL_CHECK;
+
+	send_idmef(client, idmef);
+	idmef_message_destroy(idmef);
+
+        return 0;
+
+ err:
+	syslog(LOG_ERR, "watched_exec_alert: IDMEF error: %s.\n", 
+		prelude_strerror(ret));
+        idmef_message_destroy(idmef);
+        return -1;
+}
 static void handle_event(auparse_state_t *au,
 		auparse_cb_event_t cb_event_type, void *user_data)
 {
@@ -2129,6 +2207,15 @@ static void handle_event(auparse_state_t
 				// The previous call moves the current record
 				auparse_goto_record_num(au, num);
 				break;
+			case AUDIT_TTY:
+				if (config.tty == E_NO)
+					break;
+				if (config.tty_act != A_IDMEF)
+					break;
+				if (new_alert_common(au, &idmef, &alert) >= 0){
+					tty_alert(au, idmef, alert);
+				}
+				break;
 			default:
 				break;
 		}
diff -rup audit-1.7.18/audisp/plugins/prelude/audisp-prelude.conf audit-1.7.18-ba/audisp/plugins/prelude/audisp-prelude.conf
--- audit-1.7.18/audisp/plugins/prelude/audisp-prelude.conf	2010-09-19 21:55:07.000000000 +0200
+++ audit-1.7.18-ba/audisp/plugins/prelude/audisp-prelude.conf	2011-06-17 12:19:13.000000000 +0200
@@ -56,3 +56,6 @@ watched_exec_action = idmef
 detect_watched_mk_exe = yes
 watched_mk_exe_action = idmef
 
+detect_tty = yes
+tty_action = idmef
+
Only in audit-1.7.18-ba/audisp/plugins/prelude: .audisp-prelude.c.swo
Only in audit-1.7.18-ba/audisp/plugins/prelude: libpreludedb-1.0.0
diff -rup audit-1.7.18/audisp/plugins/prelude/prelude-config.c audit-1.7.18-ba/audisp/plugins/prelude/prelude-config.c
--- audit-1.7.18/audisp/plugins/prelude/prelude-config.c	2010-09-19 21:55:07.000000000 +0200
+++ audit-1.7.18-ba/audisp/plugins/prelude/prelude-config.c	2011-04-28 10:45:27.000000000 +0200
@@ -122,6 +122,10 @@ static int watched_mk_exe_parser(struct 
 		prelude_conf_t *config);
 static int watched_mk_exe_act_parser(struct nv_pair *nv, int line, 
 		prelude_conf_t *config);
+static int tty_parser(struct nv_pair *nv, int line, 
+		prelude_conf_t *config);
+static int tty_act_parser(struct nv_pair *nv, int line, 
+		prelude_conf_t *config);
 static int sanity_check(prelude_conf_t *config, const char *file);
 
 static const struct kw_pair keywords[] = 
@@ -158,6 +162,8 @@ static const struct kw_pair keywords[] =
   {"watched_exec_action",        watched_exec_act_parser,	0 },
   {"detect_watched_mk_exe",      watched_mk_exe_parser,		0 },
   {"watched_mk_exe_action",      watched_mk_exe_act_parser,	0 },
+  {"detect_tty",                 tty_parser,		0 },
+  {"tty_action",                 tty_act_parser,	0 },
   { NULL,             NULL }
 };
 
@@ -215,6 +221,8 @@ void clear_config(prelude_conf_t *config
 	config->watched_exec_act = A_IDMEF;
 	config->watched_mk_exe = E_YES;
 	config->watched_mk_exe_act = A_IDMEF;
+	config->tty = E_YES;
+	config->tty_act = A_IDMEF;
 	ilist_create(&config->watched_accounts);
 }
 
@@ -790,6 +798,23 @@ static int watched_mk_exe_act_parser(str
         return 1;
 }
 
+static int tty_parser(struct nv_pair *nv, int line,
+	prelude_conf_t *config)
+{
+	if (lookup_enabler(nv->value, &config->tty) == 0)
+		return 0;
+        syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
+        return 1;
+}
+
+static int tty_act_parser(struct nv_pair *nv, int line,
+	prelude_conf_t *config)
+{
+	if (lookup_action(nv->value, &config->tty_act) == 0)
+		return 0;
+        syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
+        return 1;
+}
 /*
  * This function is where we do the integrated check of the audispd config
  * options. At this point, all fields have been read. Returns 0 if no
diff -rup audit-1.7.18/audisp/plugins/prelude/prelude-config.h audit-1.7.18-ba/audisp/plugins/prelude/prelude-config.h
--- audit-1.7.18/audisp/plugins/prelude/prelude-config.h	2010-09-19 21:55:07.000000000 +0200
+++ audit-1.7.18-ba/audisp/plugins/prelude/prelude-config.h	2011-04-27 12:34:21.000000000 +0200
@@ -64,6 +64,8 @@ typedef struct prelude_conf
 	action_t watched_exec_act;
 	enable_t watched_mk_exe;
 	action_t watched_mk_exe_act;
+	enable_t tty;
+	action_t tty_act;
 } prelude_conf_t;
 
 void clear_config(prelude_conf_t *config);
