--- gdm-2.19.1/config/PreSession.in.wtmp 2007-05-13 22:08:25.000000000 -0400 +++ gdm-2.19.1/config/PreSession.in 2007-05-21 13:17:09.000000000 -0400 @@ -68,17 +68,4 @@ if [ "x$XSETROOT" != "x" ] ; then "$XSETROOT" -cursor_name left_ptr -solid "$BACKCOLOR" fi - -SESSREG=`gdmwhich sessreg` -if [ "x$SESSREG" != "x" ] ; then - # some output for easy debugging - echo "$0: Registering your session with wtmp and utmp" - echo "$0: running: $SESSREG -a -w /var/log/wtmp -u /var/run/utmp -x \"$X_SERVERS\" -h \"$REMOTE_HOST\" -l \"$DISPLAY\" \"$USER\"" - - exec "$SESSREG" -a -w /var/log/wtmp -u /var/run/utmp -x "$X_SERVERS" -h "$REMOTE_HOST" -l "$DISPLAY" "$USER" - # this is not reached -fi - -# some output for easy debugging -echo "$0: could not find the sessreg utility, cannot update wtmp and utmp" exit 0 --- gdm-2.19.1/daemon/slave.c.wtmp 2007-05-21 13:17:09.000000000 -0400 +++ gdm-2.19.1/daemon/slave.c 2007-05-21 13:20:51.000000000 -0400 @@ -4426,6 +4426,13 @@ gdm_slave_session_start (void) g_free (language); g_free (gnome_session); + gdm_verify_write_record (d, + GDM_VERIFY_RECORD_TYPE_LOGIN, + pwent->pw_name, + d->name, + !d->attached? d->hostname : NULL, + pid); + gdm_slave_send_num (GDM_SOP_SESSPID, pid); gdm_sigchld_block_push (); @@ -4488,6 +4495,17 @@ gdm_slave_session_start (void) } #endif + if ((pid != 0) && (d->last_sess_status != -1)) { + gdm_debug ("session '%d' exited with status '%d', recording logout", + pid, d->last_sess_status); + gdm_verify_write_record (d, + GDM_VERIFY_RECORD_TYPE_LOGOUT, + pwent->pw_name, + d->name, + !d->attached? d->hostname : NULL, + pid); + } + gdm_slave_session_stop (pid != 0 /* run_post_session */, FALSE /* no_shutdown_check */); --- gdm-2.19.1/daemon/verify-pam.c.wtmp 2007-05-21 13:17:09.000000000 -0400 +++ gdm-2.19.1/daemon/verify-pam.c 2007-05-21 13:23:28.000000000 -0400 @@ -32,6 +32,7 @@ #ifdef __sun #include #endif +#include #include @@ -63,6 +64,14 @@ #define log_to_audit_system(l,h,d,s) do { ; } while (0) #endif +#ifndef GDM_BAD_RECORDS_FILE +#define GDM_BAD_RECORDS_FILE "/var/log/btmp" +#endif + +#ifndef GDM_NEW_RECORDS_FILE +#define GDM_NEW_RECORDS_FILE "/var/log/wtmp" +#endif + /* Evil, but this way these things are passed to the child session */ static pam_handle_t *pamh = NULL; @@ -427,6 +436,125 @@ gdm_verify_select_user (const char *user selected_user = g_strdup (user); } +void +gdm_verify_write_record (GdmDisplay *d, + GdmVerifyRecordType record_type, + const gchar *username, + const gchar *console_name, + const gchar *host_name, + GPid pid) +{ + struct utmp record = { 0 }; + GTimeVal now = { 0 }; + gchar *host; + + gdm_debug ("writing %s record", + record_type == GDM_VERIFY_RECORD_TYPE_LOGIN? "session" : + record_type == GDM_VERIFY_RECORD_TYPE_LOGOUT? "logout" : + "failed session attempt"); + + if (record_type != GDM_VERIFY_RECORD_TYPE_LOGOUT) + { + /* it's possible that PAM failed before + * it mapped the user input into a valid username + * so we fallback to try using "(unknown)" + */ + if (username != NULL) + strncpy (record.ut_user, + username, + sizeof (record.ut_user)); + else + strncpy (record.ut_user, + "(unknown)", + sizeof (record.ut_user)); + } + + gdm_debug ("using username %.*s", + sizeof (record.ut_user), + record.ut_user); + + strncpy (record.ut_id, + console_name + + strlen (console_name) - + sizeof (record.ut_id), + sizeof (record.ut_id)); + + gdm_debug ("using id %.*s", + sizeof (record.ut_id), + record.ut_id); + + if (g_str_has_prefix (console_name, "/dev/")) { + strncpy (record.ut_line, + console_name + strlen ("/dev/"), + sizeof (record.ut_line)); + } else if (g_str_has_prefix (console_name, ":")) { + strncpy (record.ut_line, + console_name, + sizeof (record.ut_line)); + } + + gdm_debug ("using line %.*s", + sizeof (record.ut_line), + record.ut_line); + + host = NULL; + if ((host_name != NULL) && + g_str_has_prefix (console_name, ":")) + host = g_strdup_printf ("%s%s", + host_name, + console_name); + else if ((host_name != NULL) && + !strstr (console_name, ":")) + host = g_strdup (host_name); + else if (!g_str_has_prefix (console_name, ":") && + strstr (console_name, ":")) + host = g_strdup (console_name); + + if (host) + { + strncpy (record.ut_host, host, sizeof (record.ut_host)); + g_free (host); + gdm_debug ("using hostname %.*s", + sizeof (record.ut_host), + record.ut_host); + } + + g_get_current_time (&now); + record.ut_tv.tv_sec = now.tv_sec; + record.ut_tv.tv_usec = now.tv_usec; + + gdm_debug ("using time %ld", (glong) record.ut_tv.tv_sec); + + record.ut_type = USER_PROCESS; + gdm_debug ("using type USER_PROCESS"); + + record.ut_pid = pid; + + gdm_debug ("using pid %d", (gint) record.ut_pid); + + switch (record_type) + { + case GDM_VERIFY_RECORD_TYPE_LOGIN: + gdm_debug ("writing session record to " + GDM_NEW_RECORDS_FILE); + updwtmp (GDM_NEW_RECORDS_FILE, &record); + break; + + case GDM_VERIFY_RECORD_TYPE_LOGOUT: + gdm_debug ("writing logout record to " + GDM_NEW_RECORDS_FILE); + updwtmp (GDM_NEW_RECORDS_FILE, &record); + break; + + case GDM_VERIFY_RECORD_TYPE_FAILED_ATTEMPT: + gdm_debug ("writing failed session attempt record to " + GDM_BAD_RECORDS_FILE); + updwtmp (GDM_BAD_RECORDS_FILE, &record); + break; + } + +} + static const char * perhaps_translate_message (const char *msg) { @@ -1234,6 +1362,11 @@ gdm_verify_user (GdmDisplay *d, * message from the PAM subsystem */ if ( ! error_msg_given && gdm_slave_action_pending ()) { + gdm_verify_write_record (d, GDM_VERIFY_RECORD_TYPE_FAILED_ATTEMPT, + login, display, + d->attached? NULL : d->hostname, + getpid ()); + /* * I'm not sure yet if I should display this message for any * other issues - heeten --- gdm-2.19.1/daemon/verify.h.wtmp 2007-05-13 22:08:25.000000000 -0400 +++ gdm-2.19.1/daemon/verify.h 2007-05-21 13:17:09.000000000 -0400 @@ -22,6 +22,12 @@ #include "gdm.h" #include "display.h" +typedef enum { + GDM_VERIFY_RECORD_TYPE_LOGIN, + GDM_VERIFY_RECORD_TYPE_LOGOUT, + GDM_VERIFY_RECORD_TYPE_FAILED_ATTEMPT +} GdmVerifyRecordType; + /* If username is NULL, we ask, if local is FALSE, don't start * the timed login timer */ gchar *gdm_verify_user (GdmDisplay *d, @@ -32,6 +38,13 @@ gchar *gdm_verify_user (GdmDisplay *d void gdm_verify_cleanup (GdmDisplay *d); void gdm_verify_check (void); void gdm_verify_select_user (const char *user); +void gdm_verify_write_record (GdmDisplay *d, + GdmVerifyRecordType record_type, + const gchar *username, + const gchar *console_name, + const gchar *host_name, + GPid pid); + /* used in pam */ gboolean gdm_verify_setup_env (GdmDisplay *d); gboolean gdm_verify_setup_user (GdmDisplay *d,