Commit 3451d349 authored by William Jon McCann's avatar William Jon McCann Committed by William Jon McCann

Separate session recording writing stuff.

2007-10-18  William Jon McCann  <mccannwj@acsnb1>

	* daemon/Makefile.am:
	* daemon/gdm-session-record.c: (gdm_session_write_record):
	* daemon/gdm-session-record.h:
	* daemon/gdm-session.c:
	(gdm_session_user_verification_error_handler),
	(gdm_session_started_handler), (gdm_session_startup_error_handler),
	(gdm_session_exited_handler), (gdm_session_close):
	Separate session recording writing stuff.


svn path=/trunk/; revision=5380
parent e0309b7b
2007-10-18 William Jon McCann <mccannwj@acsnb1>
* daemon/Makefile.am:
* daemon/gdm-session-record.c: (gdm_session_write_record):
* daemon/gdm-session-record.h:
* daemon/gdm-session.c:
(gdm_session_user_verification_error_handler),
(gdm_session_started_handler), (gdm_session_startup_error_handler),
(gdm_session_exited_handler), (gdm_session_close):
Separate session recording writing stuff.
2007-10-18 Brian Cameron <brian.cameron@sun.com>
* daemon/gdm-slave.c: Add signal.h include.
......
......@@ -94,6 +94,8 @@ gdm_simple_slave_SOURCES = \
gdm-server.h \
gdm-session.c \
gdm-session.h \
gdm-session-record.c \
gdm-session-record.h \
gdm-session-worker-job.c \
gdm-session-worker-job.h \
gdm-slave.c \
......@@ -147,6 +149,8 @@ gdm_product_slave_SOURCES = \
gdm-server.h \
gdm-session.c \
gdm-session.h \
gdm-session-record.c \
gdm-session-record.h \
gdm-session-worker-job.c \
gdm-session-worker-job.h \
gdm-slave.c \
......
/* -*- 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, 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
#ifndef GDM_NEW_SESSION_RECORDS_FILE
#define GDM_NEW_SESSION_RECORDS_FILE "/var/log/wtmp"
#endif
static void
gdm_session_write_record (GdmSessionRecordType record_type,
GPid session_pid,
const char *user_name,
const char *host_name,
const char *x11_display_name,
const char *display_device)
{
UTMP session_record = { 0 };
UTMP *u;
GTimeVal now = { 0 };
char *hostname;
char *username;
u = NULL;
g_debug ("Writing %s utmp/wtmp record",
record_type == GDM_SESSION_RECORD_TYPE_LOGIN ? "session" :
record_type == GDM_SESSION_RECORD_TYPE_LOGOUT ? "logout" :
"failed session attempt");
if (record_type != GDM_SESSION_RECORD_TYPE_LOGOUT) {
/*
* It is possible that PAM failed before it mapped the user
* input into a valid username, so we fallback to try using
* "(unknown)"
*/
if (user_name != NULL) {
username = user_name;
} else {
username = "(unknown)";
}
#if defined(HAVE_UT_UT_USER)
strncpy (session_record.ut_user,
username,
sizeof (session_record.ut_user));
g_debug ("using ut_user %.*s",
sizeof (session_record.ut_user),
session_record.ut_user);
#elif defined(HAVE_UT_UT_NAME)
strncpy (session_record.ut_name,
username
sizeof (session_record.ut_name));
g_debug ("using ut_name %.*s",
sizeof (session_record.ut_name),
session_record.ut_name);
#endif
}
#if defined(HAVE_UT_UT_TYPE)
/*
* Set type to DEAD_PROCESS when logging out, otherwise
* set to USER_PROCESS.
*/
if (record_type == GDM_SESSION_RECORD_TYPE_LOGOUT) {
session_record.ut_type = DEAD_PROCESS;
g_debug ("using ut_type DEAD_PROCESS");
} else {
session_record.ut_type = USER_PROCESS;
g_debug ("using ut_type USER_PROCESS");
}
#endif
#if defined(HAVE_UT_UT_PID)
/* Set pid */
if (session_pid != 0) {
session_record.ut_pid = session_pid;
}
g_debug ("using ut_pid %d", (int) session_record.ut_pid);
#endif
#if defined(HAVE_UT_UT_TV)
/* Set time in TV format */
g_get_current_time (&now);
session_record.ut_tv.tv_sec = now.tv_sec;
session_record.ut_tv.tv_usec = now.tv_usec;
g_debug ("using ut_tv time %ld",
(glong) session_record.ut_tv.tv_sec);
#elif defined(HAVE_UT_UT_TIME)
/* Set time in time format */
time (&session_record.ut_time);
g_debug ("using ut_time %ld",
(glong) session_record.ut_time);
#endif
#if defined(HAVE_UT_UT_ID)
/* Set ut_id to the $DISPLAY value */
strncpy (session_record.ut_id,
x11_display_name,
sizeof (session_record.ut_id));
g_debug ("using ut_id %.*s",
sizeof (session_record.ut_id),
session_record.ut_id);
#endif
#if defined(HAVE_UT_UT_HOST)
hostname = NULL;
/*
* Set ut_host to hostname:$DISPLAY if remote, otherwise set
* to $DISPLAY
*/
if ((host_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) {
strncpy (session_record.ut_host,
hostname, sizeof (session_record.ut_host));
g_debug ("using ut_host %.*s",
sizeof (session_record.ut_host),
session_record.ut_host);
g_free (hostname);
#ifdef HAVE_UT_UT_SYSLEN
session_record.ut_syslen = MIN (strlen (hostname),
sizeof (session_record.ut_host));
#endif
}
#endif
/*
* 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 (g_str_has_prefix (display_device, "/dev/")) {
strncpy (session_record.ut_line,
display_device + strlen ("/dev/"),
sizeof (session_record.ut_line));
} else if (g_str_has_prefix (x11_display_name, ":")) {
strncpy (session_record.ut_line,
x11_display_name,
sizeof (session_record.ut_line));
}
g_debug ("using ut_line %.*s",
sizeof (session_record.ut_line),
session_record.ut_line);
switch (record_type) {
case GDM_SESSION_RECORD_TYPE_LOGIN:
/* 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) && !defined(HAVE_LOGIN)
#if defined(HAVE_UT_UT_USER)
logwtmp (record.ut_line, record.ut_user, record.ut_host);
#elif defined(HAVE_UT_UT_NAME)
logwtmp (record.ut_line, record.ut_name, record.ut_host);
#endif
#endif
#if defined(HAVE_GETUTXENT)
/*
* Handle utmp
* Update if entry already exists
*/
while ((u = getutxent ()) != NULL) {
if (u->ut_type == USER_PROCESS &&
(session_record.ut_line != NULL &&
(strncmp (u->ut_line, session_record.ut_line,
sizeof (u->ut_line)) == 0 ||
u->ut_pid == session_record.ut_pid))) {
g_debug ("Updating existing utmp record");
pututxline (&session_record);
break;
}
}
endutxent ();
/* Add new entry if update did not work */
if (u == NULL) {
g_debug ("Adding new utmp record");
pututxline (&session_record);
}
#elif defined(HAVE_LOGIN)
login (&session_record);
#endif
break;
case GDM_SESSION_RECORD_TYPE_LOGOUT:
/* 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 (record.ut_line, "", "");
#endif
/* Hande utmp */
#if defined(HAVE_GETUTXENT)
setutxent ();
while ((u = getutxent ()) != NULL &&
(u = getutxid (&session_record)) != NULL) {
g_debug ("Removing utmp record");
if (u->ut_pid == session_pid &&
u->ut_type == DEAD_PROCESS) {
/* Already done */
break;
}
u->ut_type = DEAD_PROCESS;
#if defined(HAVE_UT_UT_TV)
u->ut_tv.tv_sec = session_record.ut_tv.tv_sec;
#elif defined(HAVE_UT_UT_TIME)
u->ut_time = session_record.ut_time;
#endif
u->ut_exit.e_termination = 0;
u->ut_exit.e_exit = 0;
pututxline (u);
break;
}
endutxent ();
#elif defined(HAVE_LOGOUT)
logout (session_record.ut_line);
#endif
break;
case GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT:
/* Handle btmp */
g_debug ("Writing btmp failed session attempt record to "
GDM_BAD_SESSION_RECORDS_FILE);
#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
break;
}
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
*
* 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __GDM_SESSION_RECORD_H
#define __GDM_SESSION_RECORD_H
#include <glib.h>
G_BEGIN_DECLS
typedef enum {
GDM_SESSION_RECORD_TYPE_LOGIN,
GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT,
GDM_SESSION_RECORD_TYPE_LOGOUT,
} GdmSessionRecordType;
void
gdm_session_record_write (GdmSessionRecordType record_type,
GPid session_pid,
const char *user_name,
const char *host_name,
const char *x11_display_name,
const char *display_device);
G_END_DECLS
#endif /* GDM_SESSION_RECORD_H */
......@@ -20,9 +20,6 @@
*
* TODO: - close should be nicer and shutdown
* pam etc
* - message validation code is a noop right now.
* either fix the validate functions, or drop them
* (and the sentinal magic)
* - audit libs (linux and solaris) support
*/
......@@ -34,21 +31,12 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.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>
......@@ -58,27 +46,13 @@
#include <dbus/dbus-glib-lowlevel.h>
#include "gdm-session.h"
#include "gdm-session-record.h"
#include "gdm-session-worker-job.h"
#define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session"
#define GDM_SESSION_DBUS_INTERFACE "org.gnome.DisplayManager.Session"
#define GDM_SESSION_DBUS_ERROR_NAME "org.gnome.DisplayManager.Session.Error"
#ifndef GDM_BAD_SESSION_RECORDS_FILE
#define GDM_BAD_SESSION_RECORDS_FILE "/var/log/btmp"
#endif
#ifndef GDM_NEW_SESSION_RECORDS_FILE
#define GDM_NEW_SESSION_RECORDS_FILE "/var/log/wtmp"
#endif
typedef enum _GdmSessionRecordType {
GDM_SESSION_RECORD_TYPE_LOGIN,
GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT,
GDM_SESSION_RECORD_TYPE_LOGOUT,
} GdmSessionRecordType;
struct _GdmSessionPrivate
{
GdmSessionWorkerJob *job;
......@@ -182,256 +156,16 @@ send_dbus_string_signal (GdmSession *session,
dbus_message_unref (message);
}
static void
gdm_session_write_record (GdmSession *session,
GdmSessionRecordType record_type)
{
UTMP session_record = { 0 };
UTMP *u;
GTimeVal now = { 0 };
char *hostname;
char *username;
u = NULL;
g_debug ("Writing %s utmp/wtmp record",
record_type == GDM_SESSION_RECORD_TYPE_LOGIN ? "session" :
record_type == GDM_SESSION_RECORD_TYPE_LOGOUT ? "logout" :
"failed session attempt");
if (record_type != GDM_SESSION_RECORD_TYPE_LOGOUT) {
/*
* It is possible that PAM failed before it mapped the user
* input into a valid username, so we fallback to try using
* "(unknown)"
*/
if (session->priv->username != NULL)
username = session->priv->username;
else
username = "(unknown)";
#if defined(HAVE_UT_UT_USER)
strncpy (session_record.ut_user,
username,
sizeof (session_record.ut_user));
g_debug ("using ut_user %.*s",
sizeof (session_record.ut_user),
session_record.ut_user);
#elif defined(HAVE_UT_UT_NAME)
strncpy (session_record.ut_name,
username
sizeof (session_record.ut_name));
g_debug ("using ut_name %.*s",
sizeof (session_record.ut_name),
session_record.ut_name);
#endif
}
#if defined(HAVE_UT_UT_TYPE)
/*
* Set type to DEAD_PROCESS when logging out, otherwise
* set to USER_PROCESS.
*/
if (record_type == GDM_SESSION_RECORD_TYPE_LOGOUT) {
session_record.ut_type = DEAD_PROCESS;
g_debug ("using ut_type DEAD_PROCESS");
} else {
session_record.ut_type = USER_PROCESS;
g_debug ("using ut_type USER_PROCESS");
}
#endif
#if defined(HAVE_UT_UT_PID)
/* Set pid */
if (session->priv->session_pid != 0) {
session_record.ut_pid = session->priv->session_pid;
}
g_debug ("using ut_pid %d", (int) session_record.ut_pid);
#endif
#if defined(HAVE_UT_UT_TV)
/* Set time in TV format */
g_get_current_time (&now);
session_record.ut_tv.tv_sec = now.tv_sec;
session_record.ut_tv.tv_usec = now.tv_usec;
g_debug ("using ut_tv time %ld",
(glong) session_record.ut_tv.tv_sec);
#elif defined(HAVE_UT_UT_TIME)
/* Set time in time format */
time (&session_record.ut_time);
g_debug ("using ut_time %ld",
(glong) session_record.ut_time);
#endif
#if defined(HAVE_UT_UT_ID)
/* Set ut_id to the $DISPLAY value */
strncpy (session_record.ut_id,
session->priv->x11_display_name,
sizeof (session_record.ut_id));
g_debug ("using ut_id %.*s",
sizeof (session_record.ut_id),
session_record.ut_id);
#endif
#if defined(HAVE_UT_UT_HOST)
hostname = NULL;
/*
* Set ut_host to hostname:$DISPLAY if remote, otherwise set
* to $DISPLAY
*/
if ((session->priv->hostname != NULL) &&
g_str_has_prefix (session->priv->x11_display_name, ":"))
hostname = g_strdup_printf ("%s%s", session->priv->hostname,
session->priv->x11_display_name);
else
hostname = g_strdup (session->priv->x11_display_name);
if (hostname) {
strncpy (session_record.ut_host,
hostname, sizeof (session_record.ut_host));
g_debug ("using ut_host %.*s",
sizeof (session_record.ut_host),
session_record.ut_host);
g_free (hostname);
#ifdef HAVE_UT_UT_SYSLEN
session_record.ut_syslen = MIN (strlen (hostname),
sizeof (session_record.ut_host));
#endif
}
#endif
/*
* 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 (g_str_has_prefix (session->priv->display_device, "/dev/")) {
strncpy (session_record.ut_line,
session->priv->display_device + strlen ("/dev/"),
sizeof (session_record.ut_line));
} else if (g_str_has_prefix (session->priv->x11_display_name, ":")) {
strncpy (session_record.ut_line,
session->priv->x11_display_name,
sizeof (session_record.ut_line));
}
g_debug ("using ut_line %.*s",
sizeof (session_record.ut_line),
session_record.ut_line);
switch (record_type) {
case GDM_SESSION_RECORD_TYPE_LOGIN:
/* 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) && !defined(HAVE_LOGIN)
#if defined(HAVE_UT_UT_USER)
logwtmp (record.ut_line, record.ut_user, record.ut_host);
#elif defined(HAVE_UT_UT_NAME)
logwtmp (record.ut_line, record.ut_name, record.ut_host);
#endif
#endif
#if defined(HAVE_GETUTXENT)
/*
* Handle utmp
* Update if entry already exists
*/
while ((u = getutxent ()) != NULL) {
if (u->ut_type == USER_PROCESS &&
(session_record.ut_line != NULL &&
(strncmp (u->ut_line, session_record.ut_line,
sizeof (u->ut_line)) == 0 ||
u->ut_pid == session_record.ut_pid))) {
g_debug ("Updating existing utmp record");
pututxline (&session_record);
break;
}
}
endutxent ();
/* Add new entry if update did not work */
if (u == NULL) {
g_debug ("Adding new utmp record");
pututxline (&session_record);
}
#elif defined(HAVE_LOGIN)
login (&session_record);
#endif
break;
case GDM_SESSION_RECORD_TYPE_LOGOUT:
/* 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 (record.ut_line, "", "");
#endif
/* Hande utmp */
#if defined(HAVE_GETUTXENT)
setutxent ();
while ((u = getutxent ()) != NULL &&
(u = getutxid (&session_record)) != NULL) {
g_debug ("Removing utmp record");
if (u->ut_pid == session->priv->session_pid &&
u->ut_type == DEAD_PROCESS) {
/* Already done */
break;
}
u->ut_type = DEAD_PROCESS;
#if defined(HAVE_UT_UT_TV)
u->ut_tv.tv_sec = session_record.ut_tv.tv_sec;
#elif defined(HAVE_UT_UT_TIME)
u->ut_time = session_record.ut_time;
#endif
u->ut_exit.e_termination = 0;
u->ut_exit.e_exit = 0;
pututxline (u);
break;
}
endutxent ();
#elif defined(HAVE_LOGOUT)
logout (session_record.ut_line);
#endif
break;
case GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT:
/* Handle btmp */
g_debug ("Writing btmp failed session attempt record to "
GDM_BAD_SESSION_RECORDS_FILE);
#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
break;
}
}
static void
gdm_session_user_verification_error_handler (GdmSession *session,
GError *error)
{
gdm_session_write_record (session,
GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT);
gdm_session_record_write (GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT,
session->priv->session_pid,
session->priv->user_name,
session->priv->host_name,
session->priv->x11_display_name,
session->priv->display_device);
}
static void
......@@ -439,23 +173,32 @@ gdm_session_started_handler (GdmSession *session,
GPid pid)
{
gdm_session_write_record (session,
GDM_SESSION_RECORD_TYPE_LOGIN);
gdm_session_record_write (GDM_SESSION_RECORD_TYPE_LOGIN,
);
}
static void
gdm_session_startup_error_handler (GdmSession *session,
GError *error)
{
gdm_session_write_record (session,
GDM_SESSION_RECORD_TYPE_LOGIN);
gdm_session_record (GDM_SESSION_RECORD_TYPE_LOGIN,
session->priv->session_pid,
session->priv->user_name,
session->priv->host_name,
session->priv->x11_display_name,
session->priv->display_device);
}
static void
gdm_session_exited_handler (GdmSession *session,
int exit_code)
{
gdm_session_write_record (session, GDM_SESSION_RECORD_TYPE_LOGOUT);
gdm_session_record_write (GDM_SESSION_RECORD_TYPE_LOGOUT,
session->priv->session_pid,
session->priv->user_name,
session->priv->host_name,
session->priv->x11_display_name,
session->priv->display_device);
}
static void
......@@ -1645,8 +1388,12 @@ gdm_session_close (GdmSession *session)
if (session->priv->job != NULL) {
if (session->priv->is_running) {
gdm_session_write_record (session,
GDM_SESSION_RECORD_TYPE_LOGOUT);
gdm_session_record_write (GDM_SESSION_RECORD_TYPE_LOGOUT,
session->priv->session_pid,
session->priv->user_name,
session->priv->host_name,
session->priv->x11_display_name,
session->priv->display_device);
}