diff options
Diffstat (limited to 'daemon/gdm-session-record.c')
-rw-r--r-- | daemon/gdm-session-record.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/daemon/gdm-session-record.c b/daemon/gdm-session-record.c new file mode 100644 index 0000000..7719d0a --- /dev/null +++ b/daemon/gdm-session-record.c @@ -0,0 +1,305 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2006 Ray Strode <rstrode@redhat.com> + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if defined(HAVE_UTMPX_H) +#include <utmpx.h> +#endif + +#if defined(HAVE_UTMP_H) +#include <utmp.h> +#endif + +#include <glib.h> +#include <glib/gi18n.h> +#include <glib/gstdio.h> + +#include "gdm-session-record.h" + +#ifndef GDM_BAD_SESSION_RECORDS_FILE +#define GDM_BAD_SESSION_RECORDS_FILE "/var/log/btmp" +#endif + +#if !defined(GDM_NEW_SESSION_RECORDS_FILE) +# if defined(WTMPX_FILE) +# define GDM_NEW_SESSION_RECORDS_FILE WTMPX_FILE +# elif defined(_PATH_WTMPX) +# define GDM_NEW_SESSION_RECORDS_FILE _PATH_WTMPX +# elif defined(WTMPX_FILENAME) +# define GDM_NEW_SESSION_RECORDS_FILE WTMPX_FILENAME +# elif defined(WTMP_FILE) +# define GDM_NEW_SESSION_RECORDS_FILE WTMP_FILE +# elif defined(_PATH_WTMP) /* BSD systems */ +# define GDM_NEW_SESSION_RECORDS_FILE _PATH_WTMP +# else +# define GDM_NEW_SESSION_RECORDS_FILE "/var/log/wtmp" +# endif +#endif + +static void +record_set_username (UTMP *u, + const char *username) +{ +#if defined(HAVE_UT_UT_USER) + memccpy (u->ut_user, username, '\0', sizeof (u->ut_user)); + g_debug ("using ut_user %.*s", + (int) sizeof (u->ut_user), + u->ut_user); +#elif defined(HAVE_UT_UT_NAME) + memccpy (u->ut_name, username, '\0', sizeof (u->ut_name)); + g_debug ("using ut_name %.*s", + (int) sizeof (u->ut_name), + u->ut_name); +#endif +} + +static void +record_set_timestamp (UTMP *u) +{ +#if defined(HAVE_UT_UT_TV) + GTimeVal now = { 0 }; + + /* Set time in TV format */ + g_get_current_time (&now); + u->ut_tv.tv_sec = now.tv_sec; + u->ut_tv.tv_usec = now.tv_usec; + g_debug ("using ut_tv time %ld", + (glong) u->ut_tv.tv_sec); +#elif defined(HAVE_UT_UT_TIME) + /* Set time in time format */ + time (&u->ut_time); + g_debug ("using ut_time %ld", + (glong) u->ut_time); +#endif +} + +static void +record_set_pid (UTMP *u, + GPid pid) +{ +#if defined(HAVE_UT_UT_PID) + /* Set pid */ + if (pid != 0) { + u->ut_pid = pid; + } + g_debug ("using ut_pid %d", (int) u->ut_pid); +#endif +} + +static void +record_set_host (UTMP *u, + const char *x11_display_name, + const char *host_name) +{ + char *hostname; + +#if defined(HAVE_UT_UT_HOST) + hostname = NULL; + + /* + * Set ut_host to hostname:$DISPLAY if remote, otherwise set + * to $DISPLAY + */ + if (host_name != NULL + && x11_display_name != NULL + && g_str_has_prefix (x11_display_name, ":")) { + hostname = g_strdup_printf ("%s%s", host_name, x11_display_name); + } else { + hostname = g_strdup (x11_display_name); + } + + if (hostname != NULL) { + memccpy (u->ut_host, hostname, '\0', sizeof (u->ut_host)); + g_debug ("using ut_host %.*s", (int) sizeof (u->ut_host), u->ut_host); +#ifdef HAVE_UT_UT_SYSLEN + u->ut_syslen = MIN (strlen (hostname), sizeof (u->ut_host)); +#endif + g_free (hostname); + } +#endif +} + +static void +record_set_line (UTMP *u, + const char *display_device, + const char *x11_display_name) +{ + /* + * Set ut_line to the device name associated with this display + * but remove the "/dev/" prefix. If no device, then use the + * $DISPLAY value. + */ + if (display_device != NULL + && g_str_has_prefix (display_device, "/dev/")) { + memccpy (u->ut_line, + display_device + strlen ("/dev/"), + '\0', + sizeof (u->ut_line)); + } else if (x11_display_name != NULL) { + memccpy (u->ut_line, + x11_display_name, + '\0', + sizeof (u->ut_line)); + } + + g_debug ("using ut_line %.*s", (int) sizeof (u->ut_line), u->ut_line); +} + +void +gdm_session_record_login (GPid session_pid, + const char *user_name, + const char *host_name, + const char *x11_display_name, + const char *display_device) +{ + UTMP session_record = { 0 }; + + if (x11_display_name == NULL) + x11_display_name = display_device; + + record_set_username (&session_record, user_name); + + g_debug ("Writing login record"); + +#if defined(HAVE_UT_UT_TYPE) + session_record.ut_type = USER_PROCESS; + g_debug ("using ut_type USER_PROCESS"); +#endif + + record_set_timestamp (&session_record); + record_set_pid (&session_record, session_pid); + record_set_host (&session_record, x11_display_name, host_name); + record_set_line (&session_record, display_device, x11_display_name); + + /* Handle wtmp */ + g_debug ("Writing wtmp session record to " GDM_NEW_SESSION_RECORDS_FILE); +#if defined(HAVE_UPDWTMPX) + updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record); +#elif defined(HAVE_UPDWTMP) + updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record); +#elif defined(HAVE_LOGWTMP) && defined(HAVE_UT_UT_HOST) +#if defined(HAVE_UT_UT_USER) + logwtmp (session_record.ut_line, session_record.ut_user, session_record.ut_host); +#elif defined(HAVE_UT_UT_NAME) + logwtmp (session_record.ut_line, session_record.ut_name, session_record.ut_host); +#endif +#endif + + /* Handle utmp */ +#if defined(HAVE_GETUTXENT) + g_debug ("Adding or updating utmp record for login"); + setutxent(); + pututxline (&session_record); + endutxent(); +#elif defined(HAVE_LOGIN) + login (&session_record); +#endif +} + +void +gdm_session_record_logout (GPid session_pid, + const char *user_name, + const char *host_name, + const char *x11_display_name, + const char *display_device) +{ + UTMP session_record = { 0 }; + + if (x11_display_name == NULL) + x11_display_name = display_device; + + g_debug ("Writing logout record"); + +#if defined(HAVE_UT_UT_TYPE) + session_record.ut_type = DEAD_PROCESS; + g_debug ("using ut_type DEAD_PROCESS"); +#endif + + record_set_timestamp (&session_record); + record_set_pid (&session_record, session_pid); + record_set_host (&session_record, x11_display_name, host_name); + record_set_line (&session_record, display_device, x11_display_name); + + /* Handle wtmp */ + g_debug ("Writing wtmp logout record to " GDM_NEW_SESSION_RECORDS_FILE); +#if defined(HAVE_UPDWTMPX) + updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record); +#elif defined (HAVE_UPDWTMP) + updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record); +#elif defined(HAVE_LOGWTMP) + logwtmp (session_record.ut_line, "", ""); +#endif + + /* Handle utmp */ +#if defined(HAVE_GETUTXENT) + g_debug ("Adding or updating utmp record for logout"); + setutxent(); + pututxline (&session_record); + endutxent(); +#elif defined(HAVE_LOGOUT) + logout (session_record.ut_line); +#endif +} + +void +gdm_session_record_failed (GPid session_pid, + const char *user_name, + const char *host_name, + const char *x11_display_name, + const char *display_device) +{ + UTMP session_record = { 0 }; + + if (x11_display_name == NULL) + x11_display_name = display_device; + + record_set_username (&session_record, user_name); + + g_debug ("Writing failed session attempt record"); + +#if defined(HAVE_UT_UT_TYPE) + session_record.ut_type = USER_PROCESS; + g_debug ("using ut_type USER_PROCESS"); +#endif + + record_set_timestamp (&session_record); + record_set_pid (&session_record, session_pid); + record_set_host (&session_record, x11_display_name, host_name); + record_set_line (&session_record, display_device, x11_display_name); + +#if defined(HAVE_UPDWTMPX) || defined(HAVE_UPDWTMP) + /* Handle btmp */ + g_debug ("Writing btmp failed session attempt record to " + GDM_BAD_SESSION_RECORDS_FILE); +#endif + +#if defined(HAVE_UPDWTMPX) + updwtmpx (GDM_BAD_SESSION_RECORDS_FILE, &session_record); +#elif defined(HAVE_UPDWTMP) + updwtmp(GDM_BAD_SESSION_RECORDS_FILE, &session_record); +#endif + +} |