]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - src/session-child.c
Load all users only when really needed
[sojka/lightdm.git] / src / session-child.c
index 993dd623a3f7a821edfb85cfbc3f6f82b81c8902..fb12d9b812d02f0ee9ebf3a35a53a74249cd5f0b 100644 (file)
 #include <utmpx.h>
 #include <sys/mman.h>
 
+#if HAVE_LIBAUDIT
+#include <libaudit.h>
+#endif
+
 #include "configuration.h"
 #include "session-child.h"
 #include "session.h"
+#include "console-kit.h"
 #include "login1.h"
+#include "log-file.h"
 #include "privileges.h"
 #include "x-authority.h"
 #include "configuration.h"
@@ -219,6 +225,32 @@ updwtmpx (const gchar *wtmp_file, struct utmpx *ut)
     updwtmp (wtmp_file, &u);
 }
 
+#if HAVE_LIBAUDIT
+static void
+audit_event (int type, const gchar *username, uid_t uid, const gchar *remote_host_name, const gchar *tty, gboolean success)
+{
+    int auditfd, result;
+    const char *op = NULL;
+
+    auditfd = audit_open ();
+    if (auditfd < 0) {
+        g_printerr ("Error opening audit socket: %s\n", strerror (errno));
+        return;
+    }
+
+    if (type == AUDIT_USER_LOGIN)
+        op = "login";
+    else if (type == AUDIT_USER_LOGOUT)
+        op = "logout";
+    result = success == TRUE ? 1 : 0;
+
+    if (audit_log_acct_message (auditfd, type, NULL, op, username, uid, remote_host_name, NULL, tty, result) <= 0)
+        g_printerr ("Error writing audit message: %s\n", strerror (errno));
+
+    close (auditfd);
+}
+#endif
+
 int
 session_child_run (int argc, char **argv)
 {
@@ -226,10 +258,12 @@ session_child_run (int argc, char **argv)
     int i, version, fd, result;
     gboolean auth_complete = TRUE;
     User *user = NULL;
-    gchar *log_filename, *log_backup_filename = NULL;
+    gchar *log_filename;
+    LogMode log_mode = LOG_MODE_BACKUP_AND_TRUNCATE;
     gsize env_length;
     gsize command_argc;
     gchar **command_argv;
+    GVariantBuilder ck_parameters;
     int return_code;
     int authentication_result;
     gchar *authentication_result_string;
@@ -240,10 +274,18 @@ session_child_run (int argc, char **argv)
     gchar *xdisplay;
     XAuthority *x_authority = NULL;
     gchar *x_authority_filename;
-    const gchar *login1_session = NULL;
+    GDBusConnection *bus;
+    const gchar *login1_session_id = NULL;
+    gchar *console_kit_cookie = NULL;
     const gchar *locale_value;
     gchar *locale_var;
     static const gchar * const locale_var_names[] = {
+        "LC_PAPER",
+        "LC_NAME",
+        "LC_ADDRESS",
+        "LC_TELEPHONE",
+        "LC_MEASUREMENT",
+        "LC_IDENTIFICATION",
         "LC_COLLATE",
         "LC_CTYPE",
         "LC_MONETARY",
@@ -257,6 +299,7 @@ session_child_run (int argc, char **argv)
     gid_t gid;
     uid_t uid;
     const gchar *home_directory;
+    GError *error = NULL;
 
 #if !defined(GLIB_VERSION_2_36)
     g_type_init ();
@@ -365,11 +408,8 @@ session_child_run (int argc, char **argv)
             ut.ut_type = USER_PROCESS;
             ut.ut_pid = getpid ();
             if (xdisplay)
-            {
-                strncpy (ut.ut_line, xdisplay, sizeof (ut.ut_line));
                 strncpy (ut.ut_id, xdisplay, sizeof (ut.ut_id));
-            }
-            else if (tty)
+            if (tty && g_str_has_prefix (tty, "/dev/"))
                 strncpy (ut.ut_line, tty + strlen ("/dev/"), sizeof (ut.ut_line));
             strncpy (ut.ut_user, username, sizeof (ut.ut_user));
             if (xdisplay)
@@ -381,6 +421,10 @@ session_child_run (int argc, char **argv)
             ut.ut_tv.tv_usec = tv.tv_usec;
 
             updwtmpx ("/var/log/btmp", &ut);
+
+#if HAVE_LIBAUDIT
+            audit_event (AUDIT_USER_LOGIN, username, -1, remote_host_name, tty, FALSE);
+#endif
         }
 
         /* Check account is valid */
@@ -449,6 +493,8 @@ session_child_run (int argc, char **argv)
 
     /* Get the command to run (blocks) */
     log_filename = read_string ();
+    if (version >= 3)
+        read_data (&log_mode, sizeof (log_mode));
     if (version >= 1)
     {
         g_free (tty);
@@ -483,11 +529,9 @@ session_child_run (int argc, char **argv)
     /* Redirect stderr to a log file */
     if (log_filename)
     {
-        log_backup_filename = g_strdup_printf ("%s.old", log_filename);
         if (g_path_is_absolute (log_filename))
         {
-            rename (log_filename, log_backup_filename);
-            fd = open (log_filename, O_WRONLY | O_APPEND | O_CREAT, 0600);
+            fd = log_file_open (log_filename, log_mode);
             dup2 (fd, STDERR_FILENO);
             close (fd);
             g_free (log_filename);
@@ -529,21 +573,66 @@ session_child_run (int argc, char **argv)
         return EXIT_FAILURE;
     }
 
+    /* Open a connection to the system bus for ConsoleKit - we must keep it open or CK will close the session */
+    bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+    if (error)
+        g_printerr ("Unable to contact system bus: %s", error->message);
+    if (!bus)
+    {
+        pam_end (pam_handle, 0);
+        return EXIT_FAILURE;
+    }
+
     /* Check what logind session we are, or fallback to ConsoleKit */
-    login1_session = pam_getenv (pam_handle, "XDG_SESSION_ID");
-    if (login1_session)
+    login1_session_id = pam_getenv (pam_handle, "XDG_SESSION_ID");
+    if (login1_session_id)
     {
-        write_string (login1_session);
-        /* Write what was a ConsoleKit cookie */
+        write_string (login1_session_id);
         if (version >= 2)
             write_string (NULL);
     }
     else
     {
+        g_variant_builder_init (&ck_parameters, G_VARIANT_TYPE ("(a(sv))"));
+        g_variant_builder_open (&ck_parameters, G_VARIANT_TYPE ("a(sv)"));
+        g_variant_builder_add (&ck_parameters, "(sv)", "unix-user", g_variant_new_int32 (user_get_uid (user)));
+        if (g_strcmp0 (pam_getenv (pam_handle, "XDG_SESSION_CLASS"), "greeter") == 0)
+            g_variant_builder_add (&ck_parameters, "(sv)", "session-type", g_variant_new_string ("LoginWindow"));
+        if (xdisplay)
+        {
+            g_variant_builder_add (&ck_parameters, "(sv)", "x11-display", g_variant_new_string (xdisplay));
+            if (tty)
+                g_variant_builder_add (&ck_parameters, "(sv)", "x11-display-device", g_variant_new_string (tty));
+        }
+        if (remote_host_name)
+        {
+            g_variant_builder_add (&ck_parameters, "(sv)", "is-local", g_variant_new_boolean (FALSE));
+            g_variant_builder_add (&ck_parameters, "(sv)", "remote-host-name", g_variant_new_string (remote_host_name));
+        }
+        else
+            g_variant_builder_add (&ck_parameters, "(sv)", "is-local", g_variant_new_boolean (TRUE));
+        console_kit_cookie = ck_open_session (&ck_parameters);
         if (version >= 2)
             write_string (NULL);
-        /* Write what was a ConsoleKit cookie */
-        write_string (NULL);
+        write_string (console_kit_cookie);
+        if (console_kit_cookie)
+        {
+            gchar *value;
+            gchar *runtime_dir;
+            value = g_strdup_printf ("XDG_SESSION_COOKIE=%s", console_kit_cookie);
+            pam_putenv (pam_handle, value);
+            g_free (value);
+
+            runtime_dir = ck_get_xdg_runtime_dir (console_kit_cookie);
+            if (runtime_dir)
+            {
+                gchar *value;
+                value = g_strdup_printf ("XDG_RUNTIME_DIR=%s", runtime_dir);
+                pam_putenv (pam_handle, value);
+                g_free (value);
+                g_free (runtime_dir);
+            }
+        }
     }
 
     /* Write X authority */
@@ -607,8 +696,7 @@ session_child_run (int argc, char **argv)
 
         if (log_filename)
         {
-            rename (log_filename, log_backup_filename);
-            fd = open (log_filename, O_WRONLY | O_APPEND | O_CREAT, 0600);
+            fd = log_file_open (log_filename, log_mode);
             if (fd >= 0)
             {
                 dup2 (fd, STDERR_FILENO);
@@ -616,6 +704,9 @@ session_child_run (int argc, char **argv)
             }
         }
 
+        /* Reset SIGPIPE handler so the child has default behaviour (we disabled it at LightDM start) */
+        signal (SIGPIPE, SIG_DFL);
+
         /* Run the command */
         execve (command_argv[0], command_argv, pam_getenvlist (pam_handle));
         _exit (EXIT_FAILURE);
@@ -641,11 +732,8 @@ session_child_run (int argc, char **argv)
             ut.ut_type = USER_PROCESS;
             ut.ut_pid = child_pid;
             if (xdisplay)
-            {
-                strncpy (ut.ut_line, xdisplay, sizeof (ut.ut_line));
                 strncpy (ut.ut_id, xdisplay, sizeof (ut.ut_id));
-            }
-            else if (tty)
+            if (tty && g_str_has_prefix (tty, "/dev/"))
                 strncpy (ut.ut_line, tty + strlen ("/dev/"), sizeof (ut.ut_line));
             strncpy (ut.ut_user, username, sizeof (ut.ut_user));
             if (xdisplay)
@@ -662,6 +750,10 @@ session_child_run (int argc, char **argv)
                 g_printerr ("Failed to write utmpx: %s\n", strerror (errno));
             endutxent ();
             updwtmpx ("/var/log/wtmp", &ut);
+
+#if HAVE_LIBAUDIT          
+            audit_event (AUDIT_USER_LOGIN, username, uid, remote_host_name, tty, TRUE);
+#endif
         }
 
         waitpid (child_pid, &return_code, 0);
@@ -677,11 +769,8 @@ session_child_run (int argc, char **argv)
             ut.ut_type = DEAD_PROCESS;
             ut.ut_pid = child_pid;
             if (xdisplay)
-            {
-                strncpy (ut.ut_line, xdisplay, sizeof (ut.ut_line));
                 strncpy (ut.ut_id, xdisplay, sizeof (ut.ut_id));
-            }
-            else if (tty)
+            if (tty && g_str_has_prefix (tty, "/dev/"))
                 strncpy (ut.ut_line, tty + strlen ("/dev/"), sizeof (ut.ut_line));
             strncpy (ut.ut_user, username, sizeof (ut.ut_user));
             if (xdisplay)
@@ -698,6 +787,10 @@ session_child_run (int argc, char **argv)
                 g_printerr ("Failed to write utmpx: %s\n", strerror (errno));
             endutxent ();
             updwtmpx ("/var/log/wtmp", &ut);
+
+#if HAVE_LIBAUDIT
+            audit_event (AUDIT_USER_LOGOUT, username, uid, remote_host_name, tty, TRUE);
+#endif
         }
     }
 
@@ -721,11 +814,15 @@ session_child_run (int argc, char **argv)
             _exit (EXIT_FAILURE);
     }
 
+    /* Close the Console Kit session */
+    if (console_kit_cookie)
+        ck_close_session (console_kit_cookie);
+
     /* Close the session */
     pam_close_session (pam_handle, 0);
 
     /* Remove credentials */
-    result = pam_setcred (pam_handle, PAM_DELETE_CRED);
+    pam_setcred (pam_handle, PAM_DELETE_CRED);
 
     pam_end (pam_handle, 0);
     pam_handle = NULL;