Blame SOURCES/just-in-time-reauthentication.patch

01018b
From 16adbf262b641ec722794a30a91097767d13fc16 Mon Sep 17 00:00:00 2001
01018b
From: Ray Strode <rstrode@redhat.com>
01018b
Date: Wed, 12 Feb 2014 14:22:31 -0500
01018b
Subject: [PATCH 1/4] manager: explicitly disallow login screen from opening
01018b
 reauth channel
01018b
01018b
It doesn't make sense for it to do, and right now the shell does it
01018b
up front, waits for the failure, and then does the "right" thing
01018b
(opens a new auth session) after.
01018b
01018b
This commit makes the failure explicit, so we can subsequently make
01018b
other cases where a reauth channel is requested work even if there is
01018b
no session to channel to by implicitly creating a transient one just
01018b
in time.  That will come later.
01018b
---
01018b
 daemon/gdm-manager.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++---
01018b
 1 file changed, 116 insertions(+), 6 deletions(-)
01018b
01018b
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
01018b
index 6c0fe1d..6ce37e8 100644
01018b
--- a/daemon/gdm-manager.c
01018b
+++ b/daemon/gdm-manager.c
01018b
@@ -244,192 +244,302 @@ get_uid_for_session_id (GDBusConnection  *connection,
01018b
         if (LOGIND_RUNNING()) {
01018b
                 return get_uid_for_systemd_session_id (session_id, uid, error);
01018b
         }
01018b
 #endif
01018b
 
01018b
 #ifdef WITH_CONSOLE_KIT
01018b
         return get_uid_for_consolekit_session_id (connection, session_id, uid, error);
01018b
 #endif
01018b
 
01018b
         return FALSE;
01018b
 }
01018b
 
01018b
 static gboolean
01018b
 lookup_by_session_id (const char *id,
01018b
                       GdmDisplay *display,
01018b
                       gpointer    user_data)
01018b
 {
01018b
         const char *looking_for = user_data;
01018b
         char *current;
01018b
         gboolean res;
01018b
 
01018b
         current = gdm_display_get_session_id (display);
01018b
 
01018b
         res = g_strcmp0 (current, looking_for) == 0;
01018b
 
01018b
         g_free (current);
01018b
 
01018b
         return res;
01018b
 }
01018b
 
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+static gboolean
01018b
+is_consolekit_login_session (GdmManager       *self,
01018b
+                             GDBusConnection  *connection,
01018b
+                             const char       *session_id,
01018b
+                             GError          **error)
01018b
+{
01018b
+        GVariant *reply;
01018b
+        char *session_type = NULL;
01018b
+
01018b
+        reply = g_dbus_connection_call_sync (connection,
01018b
+                                             "org.freedesktop.ConsoleKit",
01018b
+                                             session_id,
01018b
+                                             "org.freedesktop.ConsoleKit.Session",
01018b
+                                             "GetSessionType",
01018b
+                                             NULL,
01018b
+                                             G_VARIANT_TYPE ("(s)"),
01018b
+                                             G_DBUS_CALL_FLAGS_NONE,
01018b
+                                             -1,
01018b
+                                             NULL,
01018b
+                                             error);
01018b
+        if (reply == NULL) {
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        g_variant_get (reply, "(s)", &session_type);
01018b
+        g_variant_unref (reply);
01018b
+
01018b
+        if (g_strcmp0 (session_type, "LoginWindow") != 0) {
01018b
+                g_free (session_type);
01018b
+
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        g_free (session_type);
01018b
+        return TRUE;
01018b
+}
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_SYSTEMD
01018b
+static gboolean
01018b
+is_systemd_login_session (GdmManager  *self,
01018b
+                          const char  *session_id,
01018b
+                          GError     **error)
01018b
+{
01018b
+        char *session_class = NULL;
01018b
+        int ret;
01018b
+
01018b
+        ret = sd_session_get_class (session_id, &session_class);
01018b
+
01018b
+        if (ret < 0) {
01018b
+                g_set_error (error,
01018b
+                             GDM_DISPLAY_ERROR,
01018b
+                             GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
01018b
+                             "Error getting class for session id %s from systemd: %s",
01018b
+                             session_id,
01018b
+                             g_strerror (-ret));
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        if (g_strcmp0 (session_class, "greeter") != 0) {
01018b
+                g_free (session_class);
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        g_free (session_class);
01018b
+        return TRUE;
01018b
+}
01018b
+#endif
01018b
+
01018b
+static gboolean
01018b
+is_login_session (GdmManager       *self,
01018b
+                  GDBusConnection  *connection,
01018b
+                  const char       *session_id,
01018b
+                  GError          **error)
01018b
+{
01018b
+#ifdef WITH_SYSTEMD
01018b
+        if (LOGIND_RUNNING()) {
01018b
+                return is_systemd_login_session (self, session_id, error);
01018b
+        }
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+        return is_consolekit_login_session (self, connection, session_id, error);
01018b
+#endif
01018b
+
01018b
+        return FALSE;
01018b
+}
01018b
+
01018b
 static GdmDisplay *
01018b
 get_display_and_details_for_bus_sender (GdmManager       *self,
01018b
-                            GDBusConnection  *connection,
01018b
-                            const char       *sender,
01018b
-                            GPid             *out_pid,
01018b
-                            uid_t            *out_uid)
01018b
+                                        GDBusConnection  *connection,
01018b
+                                        const char       *sender,
01018b
+                                        GPid             *out_pid,
01018b
+                                        uid_t            *out_uid,
01018b
+                                        gboolean         *out_is_login_screen)
01018b
 {
01018b
         GdmDisplay *display = NULL;
01018b
         char       *session_id = NULL;
01018b
         GError     *error = NULL;
01018b
         int         ret;
01018b
         GPid        pid;
01018b
         uid_t       caller_uid, session_uid;
01018b
 
01018b
         ret = gdm_dbus_get_pid_for_name (sender, &pid, &error);
01018b
 
01018b
         if (!ret) {
01018b
                 g_debug ("GdmManager: Error while retrieving pid for sender: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
         ret = gdm_dbus_get_uid_for_name (sender, &caller_uid, &error);
01018b
 
01018b
         if (!ret) {
01018b
                 g_debug ("GdmManager: Error while retrieving uid for sender: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
         session_id = get_session_id_for_pid (connection, pid, &error);
01018b
 
01018b
         if (session_id == NULL) {
01018b
                 g_debug ("GdmManager: Error while retrieving session id for sender: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
+        if (out_is_login_screen != NULL) {
01018b
+                *out_is_login_screen = is_login_session (self, connection, session_id, &error);
01018b
+
01018b
+                if (error != NULL) {
01018b
+                        g_debug ("GdmManager: Error while checking if sender is login screen: %s",
01018b
+                                 error->message);
01018b
+                        g_error_free (error);
01018b
+                        goto out;
01018b
+                }
01018b
+        }
01018b
+
01018b
         if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) {
01018b
                 g_debug ("GdmManager: Error while retrieving uid for session: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
         if (caller_uid != session_uid) {
01018b
                 g_debug ("GdmManager: uid for sender and uid for session don't match");
01018b
                 goto out;
01018b
         }
01018b
 
01018b
         display = gdm_display_store_find (self->priv->display_store,
01018b
                                           lookup_by_session_id,
01018b
                                           (gpointer) session_id);
01018b
 out:
01018b
         g_free (session_id);
01018b
 
01018b
         if (display != NULL) {
01018b
             if (out_pid != NULL)
01018b
                 *out_pid = pid;
01018b
 
01018b
             if (out_uid != NULL)
01018b
                 *out_uid = session_uid;
01018b
         }
01018b
         return display;
01018b
 }
01018b
 
01018b
 static gboolean
01018b
 gdm_manager_handle_open_session (GdmDBusManager        *manager,
01018b
                                  GDBusMethodInvocation *invocation)
01018b
 {
01018b
         GdmManager       *self = GDM_MANAGER (manager);
01018b
         const char       *sender = NULL;
01018b
         GError           *error = NULL;
01018b
         GDBusConnection  *connection;
01018b
         GdmDisplay       *display;
01018b
         char             *address;
01018b
         GPid              pid;
01018b
         uid_t             uid;
01018b
 
01018b
         g_debug ("GdmManager: trying to open new session");
01018b
 
01018b
         sender = g_dbus_method_invocation_get_sender (invocation);
01018b
         connection = g_dbus_method_invocation_get_connection (invocation);
01018b
-        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid);
01018b
+        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid, NULL);
01018b
 
01018b
         if (display == NULL) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("No session available"));
01018b
 
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         address = gdm_display_open_session_sync (display, pid, uid, NULL, &error);
01018b
 
01018b
         if (address == NULL) {
01018b
                 g_dbus_method_invocation_return_gerror (invocation, error);
01018b
                 g_error_free (error);
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager),
01018b
                                                 invocation,
01018b
                                                 address);
01018b
         g_free (address);
01018b
 
01018b
         return TRUE;
01018b
 }
01018b
 
01018b
 static gboolean
01018b
 gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager,
01018b
                                                   GDBusMethodInvocation *invocation,
01018b
                                                   const char            *username)
01018b
 {
01018b
         GdmManager       *self = GDM_MANAGER (manager);
01018b
         const char       *sender = NULL;
01018b
         GError           *error = NULL;
01018b
         GDBusConnection  *connection;
01018b
         GdmDisplay       *display;
01018b
         char             *address;
01018b
         GPid              pid;
01018b
         uid_t             uid;
01018b
+        gboolean          is_login_screen = FALSE;
01018b
 
01018b
         g_debug ("GdmManager: trying to open reauthentication channel for user %s", username);
01018b
 
01018b
         sender = g_dbus_method_invocation_get_sender (invocation);
01018b
         connection = g_dbus_method_invocation_get_connection (invocation);
01018b
-        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid);
01018b
+        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid, &is_login_screen);
01018b
+
01018b
+        if (is_login_screen) {
01018b
+                g_dbus_method_invocation_return_error_literal (invocation,
01018b
+                                                               G_DBUS_ERROR,
01018b
+                                                               G_DBUS_ERROR_ACCESS_DENIED,
01018b
+                                                               _("Login screen not allow to open reauthentication channel"));
01018b
+                return TRUE;
01018b
+        }
01018b
 
01018b
         if (display == NULL) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("No session available"));
01018b
 
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         address = gdm_display_open_reauthentication_channel_sync (display,
01018b
                                                                   username,
01018b
                                                                   pid,
01018b
                                                                   uid,
01018b
                                                                   NULL,
01018b
                                                                   &error);
01018b
 
01018b
         if (address == NULL) {
01018b
                 g_dbus_method_invocation_return_gerror (invocation, error);
01018b
                 g_error_free (error);
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
01018b
                                                                  invocation,
01018b
                                                                  address);
01018b
         g_free (address);
01018b
 
01018b
         return TRUE;
01018b
 }
01018b
-- 
01018b
1.8.4.2
01018b
01018b
01018b
From 3a1330c93213a060c51b2d3021360e80a779814c Mon Sep 17 00:00:00 2001
01018b
From: Ray Strode <rstrode@redhat.com>
01018b
Date: Tue, 11 Mar 2014 23:46:35 -0400
01018b
Subject: [PATCH 2/4] worker: support authentication without X11 display
01018b
01018b
At the moment we unconditionally set PAM_XDISPLAY
01018b
and PAM_XAUTHDATA based on values passed to the worker.
01018b
01018b
In a future commit, those values are going to become
01018b
stubs, so as a first step, this commit makes PAM_XDISPLAY
01018b
and PAM_XAUTHDATA optional.
01018b
---
01018b
 daemon/gdm-session-worker.c | 11 ++++++++---
01018b
 1 file changed, 8 insertions(+), 3 deletions(-)
01018b
01018b
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
01018b
index 79cf202..eb81450 100644
01018b
--- a/daemon/gdm-session-worker.c
01018b
+++ b/daemon/gdm-session-worker.c
01018b
@@ -1073,76 +1073,81 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
01018b
 
01018b
         /* set TTY */
01018b
         pam_tty = _get_tty_for_pam (x11_display_name, display_device);
01018b
         if (pam_tty != NULL && pam_tty[0] != '\0') {
01018b
                 error_code = pam_set_item (worker->priv->pam_handle, PAM_TTY, pam_tty);
01018b
         }
01018b
         g_free (pam_tty);
01018b
 
01018b
         if (error_code != PAM_SUCCESS) {
01018b
                 g_set_error (error,
01018b
                              GDM_SESSION_WORKER_ERROR,
01018b
                              GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
01018b
                              _("error informing authentication system of user's console: %s"),
01018b
                              pam_strerror (worker->priv->pam_handle, error_code));
01018b
                 goto out;
01018b
         }
01018b
 
01018b
 #ifdef WITH_SYSTEMD
01018b
         /* set seat ID */
01018b
         if (seat_id != NULL && seat_id[0] != '\0' && LOGIND_RUNNING()) {
01018b
                 gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
01018b
         }
01018b
 #endif
01018b
 
01018b
         if (strcmp (service, "gdm-launch-environment") == 0) {
01018b
                 gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
01018b
         }
01018b
 
01018b
 #ifdef PAM_XDISPLAY
01018b
         /* set XDISPLAY */
01018b
-        error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, x11_display_name);
01018b
+        if (x11_display_name != NULL && x11_display_name[0] != '\0') {
01018b
+                error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, x11_display_name);
01018b
+        }
01018b
 
01018b
         if (error_code != PAM_SUCCESS) {
01018b
                 g_set_error (error,
01018b
                              GDM_SESSION_WORKER_ERROR,
01018b
                              GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
01018b
                              _("error informing authentication system of display string: %s"),
01018b
                              pam_strerror (worker->priv->pam_handle, error_code));
01018b
                 goto out;
01018b
         }
01018b
 #endif
01018b
 #ifdef PAM_XAUTHDATA
01018b
         /* set XAUTHDATA */
01018b
         pam_xauth = _get_xauth_for_pam (x11_authority_file);
01018b
-        error_code = pam_set_item (worker->priv->pam_handle, PAM_XAUTHDATA, pam_xauth);
01018b
-        g_free (pam_xauth);
01018b
+
01018b
+        if (pam_xauth != NULL) {
01018b
+                error_code = pam_set_item (worker->priv->pam_handle, PAM_XAUTHDATA, pam_xauth);
01018b
+                g_free (pam_xauth);
01018b
+        }
01018b
 
01018b
         if (error_code != PAM_SUCCESS) {
01018b
                 g_set_error (error,
01018b
                              GDM_SESSION_WORKER_ERROR,
01018b
                              GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
01018b
                              _("error informing authentication system of display xauth credentials: %s"),
01018b
                              pam_strerror (worker->priv->pam_handle, error_code));
01018b
                 goto out;
01018b
         }
01018b
 #endif
01018b
 
01018b
         g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
01018b
         worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE;
01018b
 
01018b
  out:
01018b
         if (error_code != PAM_SUCCESS) {
01018b
                 gdm_session_worker_uninitialize_pam (worker, error_code);
01018b
                 return FALSE;
01018b
         }
01018b
 
01018b
         return TRUE;
01018b
 }
01018b
 
01018b
 static gboolean
01018b
 gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
01018b
                                       gboolean          password_is_required,
01018b
                                       GError          **error)
01018b
 {
01018b
         int error_code;
01018b
         int authentication_flags;
01018b
-- 
01018b
1.8.4.2
01018b
01018b
01018b
From e8c249d57b744d61c3c119f55e26f1ff1c14a598 Mon Sep 17 00:00:00 2001
01018b
From: Ray Strode <rstrode@redhat.com>
01018b
Date: Wed, 19 Feb 2014 10:54:56 -0500
01018b
Subject: [PATCH 3/4] manager: collect more details about bus sender
01018b
01018b
In the future we're going to need to know more details about the
01018b
sender to know how to move forward (such as seat id, session id,
01018b
if it's remote, etc) in order to create a transient session soley
01018b
for reauthentication.
01018b
01018b
To prepare for that future, this commit adds the necessary
01018b
functionality to get_display_and_details_for_bus_sender.
01018b
---
01018b
 daemon/gdm-manager.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++-----
01018b
 1 file changed, 209 insertions(+), 19 deletions(-)
01018b
01018b
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
01018b
index 6ce37e8..4c47045 100644
01018b
--- a/daemon/gdm-manager.c
01018b
+++ b/daemon/gdm-manager.c
01018b
@@ -333,205 +333,395 @@ is_systemd_login_session (GdmManager  *self,
01018b
 
01018b
         if (g_strcmp0 (session_class, "greeter") != 0) {
01018b
                 g_free (session_class);
01018b
                 return FALSE;
01018b
         }
01018b
 
01018b
         g_free (session_class);
01018b
         return TRUE;
01018b
 }
01018b
 #endif
01018b
 
01018b
 static gboolean
01018b
 is_login_session (GdmManager       *self,
01018b
                   GDBusConnection  *connection,
01018b
                   const char       *session_id,
01018b
                   GError          **error)
01018b
 {
01018b
 #ifdef WITH_SYSTEMD
01018b
         if (LOGIND_RUNNING()) {
01018b
                 return is_systemd_login_session (self, session_id, error);
01018b
         }
01018b
 #endif
01018b
 
01018b
 #ifdef WITH_CONSOLE_KIT
01018b
         return is_consolekit_login_session (self, connection, session_id, error);
01018b
 #endif
01018b
 
01018b
         return FALSE;
01018b
 }
01018b
 
01018b
-static GdmDisplay *
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+static gboolean
01018b
+is_consolekit_remote_session (GdmManager       *self,
01018b
+                             GDBusConnection  *connection,
01018b
+                             const char       *session_id,
01018b
+                             GError          **error)
01018b
+{
01018b
+        GVariant *reply;
01018b
+        gboolean is_remote;
01018b
+
01018b
+        reply = g_dbus_connection_call_sync (connection,
01018b
+                                             "org.freedesktop.ConsoleKit",
01018b
+                                             session_id,
01018b
+                                             "org.freedesktop.ConsoleKit.Session",
01018b
+                                             "IsLocal",
01018b
+                                             NULL,
01018b
+                                             G_VARIANT_TYPE ("(b)"),
01018b
+                                             G_DBUS_CALL_FLAGS_NONE,
01018b
+                                             -1,
01018b
+                                             NULL,
01018b
+                                             error);
01018b
+        if (reply == NULL) {
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        g_variant_get (reply, "(b)", &is_remote);
01018b
+        g_variant_unref (reply);
01018b
+
01018b
+        return is_remote;
01018b
+}
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_SYSTEMD
01018b
+static gboolean
01018b
+is_systemd_remote_session (GdmManager  *self,
01018b
+                           const char  *session_id,
01018b
+                           GError     **error)
01018b
+{
01018b
+        char *seat;
01018b
+        int ret;
01018b
+        gboolean is_remote;
01018b
+
01018b
+        /* FIXME: The next release of logind is going to have explicit api for
01018b
+         * checking remoteness.
01018b
+         */
01018b
+        seat = NULL;
01018b
+        ret = sd_session_get_seat (session_id, &seat;;
01018b
+
01018b
+        if (ret < 0 && ret != -ENOENT) {
01018b
+                g_debug ("GdmManager: Error while retrieving seat for session %s: %s",
01018b
+                         session_id, strerror (-ret));
01018b
+        }
01018b
+
01018b
+        if (seat != NULL) {
01018b
+                is_remote = FALSE;
01018b
+                free (seat);
01018b
+        } else {
01018b
+                is_remote = TRUE;
01018b
+        }
01018b
+
01018b
+        return is_remote;
01018b
+}
01018b
+#endif
01018b
+
01018b
+static gboolean
01018b
+is_remote_session (GdmManager       *self,
01018b
+                  GDBusConnection  *connection,
01018b
+                  const char       *session_id,
01018b
+                  GError          **error)
01018b
+{
01018b
+#ifdef WITH_SYSTEMD
01018b
+        if (LOGIND_RUNNING()) {
01018b
+                return is_systemd_remote_session (self, session_id, error);
01018b
+        }
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+        return is_consolekit_remote_session (self, connection, session_id, error);
01018b
+#endif
01018b
+
01018b
+        return FALSE;
01018b
+}
01018b
+
01018b
+#ifdef WITH_SYSTEMD
01018b
+static char *
01018b
+get_seat_id_for_systemd_session_id (const char  *session_id,
01018b
+                                    GError     **error)
01018b
+{
01018b
+        int ret;
01018b
+        char *seat, *out_seat;
01018b
+
01018b
+        seat = NULL;
01018b
+        ret = sd_session_get_seat (session_id, &seat;;
01018b
+
01018b
+        if (ret == -ENOENT) {
01018b
+                out_seat = NULL;
01018b
+        } else if (ret < 0) {
01018b
+                g_set_error (error,
01018b
+                             GDM_DISPLAY_ERROR,
01018b
+                             GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
01018b
+                             "Error getting uid for session id %s from systemd: %s",
01018b
+                             session_id,
01018b
+                             g_strerror (-ret));
01018b
+                out_seat = NULL;
01018b
+        } else {
01018b
+                out_seat = g_strdup (seat);
01018b
+                free (seat);
01018b
+        }
01018b
+
01018b
+        return out_seat;
01018b
+}
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+static char *
01018b
+get_seat_id_for_consolekit_session_id (GDBusConnection  *connection,
01018b
+                                       const char       *session_id,
01018b
+                                       GError          **error)
01018b
+{
01018b
+        GVariant *reply;
01018b
+        char *retval;
01018b
+
01018b
+        reply = g_dbus_connection_call_sync (connection,
01018b
+                                             "org.freedesktop.ConsoleKit",
01018b
+                                             session_id,
01018b
+                                             "org.freedesktop.ConsoleKit.Session",
01018b
+                                             "GetSeatId",
01018b
+                                             NULL,
01018b
+                                             G_VARIANT_TYPE ("(o)"),
01018b
+                                             G_DBUS_CALL_FLAGS_NONE,
01018b
+                                             -1,
01018b
+                                             NULL,
01018b
+                                             error);
01018b
+        if (reply == NULL) {
01018b
+                return NULL;
01018b
+        }
01018b
+
01018b
+        g_variant_get (reply, "(o)", &retval);
01018b
+        g_variant_unref (reply);
01018b
+
01018b
+        return retval;
01018b
+}
01018b
+#endif
01018b
+
01018b
+static char *
01018b
+get_seat_id_for_session_id (GDBusConnection  *connection,
01018b
+                            const char       *session_id,
01018b
+                            GError          **error)
01018b
+{
01018b
+#ifdef WITH_SYSTEMD
01018b
+        if (LOGIND_RUNNING()) {
01018b
+                return get_seat_id_for_systemd_session_id (session_id, error);
01018b
+        }
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+        return get_seat_id_for_consolekit_session_id (connection, session_id, error);
01018b
+#endif
01018b
+
01018b
+        return NULL;
01018b
+}
01018b
+
01018b
+static void
01018b
 get_display_and_details_for_bus_sender (GdmManager       *self,
01018b
                                         GDBusConnection  *connection,
01018b
                                         const char       *sender,
01018b
+                                        GdmDisplay      **out_display,
01018b
+                                        char            **out_seat_id,
01018b
+                                        char            **out_session_id,
01018b
                                         GPid             *out_pid,
01018b
                                         uid_t            *out_uid,
01018b
-                                        gboolean         *out_is_login_screen)
01018b
+                                        gboolean         *out_is_login_screen,
01018b
+                                        gboolean         *out_is_remote)
01018b
 {
01018b
         GdmDisplay *display = NULL;
01018b
         char       *session_id = NULL;
01018b
         GError     *error = NULL;
01018b
         int         ret;
01018b
         GPid        pid;
01018b
         uid_t       caller_uid, session_uid;
01018b
 
01018b
         ret = gdm_dbus_get_pid_for_name (sender, &pid, &error);
01018b
 
01018b
         if (!ret) {
01018b
                 g_debug ("GdmManager: Error while retrieving pid for sender: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
+        if (out_pid != NULL)
01018b
+            *out_pid = pid;
01018b
+
01018b
         ret = gdm_dbus_get_uid_for_name (sender, &caller_uid, &error);
01018b
 
01018b
         if (!ret) {
01018b
                 g_debug ("GdmManager: Error while retrieving uid for sender: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
         session_id = get_session_id_for_pid (connection, pid, &error);
01018b
 
01018b
         if (session_id == NULL) {
01018b
                 g_debug ("GdmManager: Error while retrieving session id for sender: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
+        if (out_session_id != NULL) {
01018b
+                *out_session_id = g_strdup (session_id);
01018b
+        }
01018b
+
01018b
         if (out_is_login_screen != NULL) {
01018b
                 *out_is_login_screen = is_login_session (self, connection, session_id, &error);
01018b
 
01018b
                 if (error != NULL) {
01018b
                         g_debug ("GdmManager: Error while checking if sender is login screen: %s",
01018b
                                  error->message);
01018b
                         g_error_free (error);
01018b
                         goto out;
01018b
                 }
01018b
         }
01018b
 
01018b
         if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) {
01018b
                 g_debug ("GdmManager: Error while retrieving uid for session: %s",
01018b
                          error->message);
01018b
                 g_error_free (error);
01018b
                 goto out;
01018b
         }
01018b
 
01018b
+        if (out_uid != NULL)
01018b
+            *out_uid = session_uid;
01018b
+
01018b
         if (caller_uid != session_uid) {
01018b
                 g_debug ("GdmManager: uid for sender and uid for session don't match");
01018b
                 goto out;
01018b
         }
01018b
 
01018b
+        if (out_seat_id != NULL) {
01018b
+                *out_seat_id = get_seat_id_for_session_id (connection, session_id, &error);
01018b
+
01018b
+                if (error != NULL) {
01018b
+                        g_debug ("GdmManager: Error while retrieving seat id for session: %s",
01018b
+                                 error->message);
01018b
+                        g_clear_error (&error);
01018b
+                }
01018b
+        }
01018b
+
01018b
+        if (out_is_remote != NULL) {
01018b
+                *out_is_remote = is_remote_session (self, connection, session_id, &error);
01018b
+
01018b
+                if (error != NULL) {
01018b
+                        g_debug ("GdmManager: Error while retrieving remoteness for session: %s",
01018b
+                                 error->message);
01018b
+                        g_clear_error (&error);
01018b
+                }
01018b
+        }
01018b
+
01018b
         display = gdm_display_store_find (self->priv->display_store,
01018b
                                           lookup_by_session_id,
01018b
                                           (gpointer) session_id);
01018b
+        if (out_display != NULL)
01018b
+            *out_display = display;
01018b
+
01018b
 out:
01018b
         g_free (session_id);
01018b
-
01018b
-        if (display != NULL) {
01018b
-            if (out_pid != NULL)
01018b
-                *out_pid = pid;
01018b
-
01018b
-            if (out_uid != NULL)
01018b
-                *out_uid = session_uid;
01018b
-        }
01018b
-        return display;
01018b
 }
01018b
 
01018b
 static gboolean
01018b
 gdm_manager_handle_open_session (GdmDBusManager        *manager,
01018b
                                  GDBusMethodInvocation *invocation)
01018b
 {
01018b
         GdmManager       *self = GDM_MANAGER (manager);
01018b
         const char       *sender = NULL;
01018b
         GError           *error = NULL;
01018b
         GDBusConnection  *connection;
01018b
-        GdmDisplay       *display;
01018b
+        GdmDisplay       *display = NULL;
01018b
         char             *address;
01018b
-        GPid              pid;
01018b
-        uid_t             uid;
01018b
+        GPid              pid = 0;
01018b
+        uid_t             uid = (uid_t) -1;
01018b
 
01018b
         g_debug ("GdmManager: trying to open new session");
01018b
 
01018b
         sender = g_dbus_method_invocation_get_sender (invocation);
01018b
         connection = g_dbus_method_invocation_get_connection (invocation);
01018b
-        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid, NULL);
01018b
+        get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, &pid, &uid, NULL, NULL);
01018b
 
01018b
         if (display == NULL) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("No session available"));
01018b
 
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         address = gdm_display_open_session_sync (display, pid, uid, NULL, &error);
01018b
 
01018b
         if (address == NULL) {
01018b
                 g_dbus_method_invocation_return_gerror (invocation, error);
01018b
                 g_error_free (error);
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager),
01018b
                                                 invocation,
01018b
                                                 address);
01018b
         g_free (address);
01018b
 
01018b
         return TRUE;
01018b
 }
01018b
 
01018b
 static gboolean
01018b
 gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager,
01018b
                                                   GDBusMethodInvocation *invocation,
01018b
                                                   const char            *username)
01018b
 {
01018b
         GdmManager       *self = GDM_MANAGER (manager);
01018b
         const char       *sender = NULL;
01018b
         GError           *error = NULL;
01018b
         GDBusConnection  *connection;
01018b
-        GdmDisplay       *display;
01018b
+        GdmDisplay       *display = NULL;
01018b
         char             *address;
01018b
-        GPid              pid;
01018b
-        uid_t             uid;
01018b
+        GPid              pid = 0;
01018b
+        uid_t             uid = (uid_t) -1;
01018b
         gboolean          is_login_screen = FALSE;
01018b
 
01018b
         g_debug ("GdmManager: trying to open reauthentication channel for user %s", username);
01018b
 
01018b
         sender = g_dbus_method_invocation_get_sender (invocation);
01018b
         connection = g_dbus_method_invocation_get_connection (invocation);
01018b
-        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid, &is_login_screen);
01018b
+        get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, &pid, &uid, &is_login_screen, NULL);
01018b
 
01018b
         if (is_login_screen) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("Login screen not allow to open reauthentication channel"));
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         if (display == NULL) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("No session available"));
01018b
 
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         address = gdm_display_open_reauthentication_channel_sync (display,
01018b
                                                                   username,
01018b
                                                                   pid,
01018b
                                                                   uid,
01018b
                                                                   NULL,
01018b
                                                                   &error);
01018b
 
01018b
         if (address == NULL) {
01018b
                 g_dbus_method_invocation_return_gerror (invocation, error);
01018b
                 g_error_free (error);
01018b
                 return TRUE;
01018b
         }
01018b
-- 
01018b
1.8.4.2
01018b
01018b
01018b
From 8fe36a032eb5ce681c91d5ccc8b0719f8e360b53 Mon Sep 17 00:00:00 2001
01018b
From: Ray Strode <rstrode@redhat.com>
01018b
Date: Tue, 11 Mar 2014 15:25:29 -0400
01018b
Subject: [PATCH 4/4] manager: support just-in-time reauthentication for
01018b
 non-GDM sessions
01018b
01018b
Right now, gnome-shell can't unlock screens running on an X server that
01018b
isn't managed by GDM (say Xvnc or startx).  This is because GDM handles
01018b
the backend processing for unlocking, and it handles that backend
01018b
processing from the worker associated with the session.  If there is no
01018b
worker associated with the session (as is the case with Xvnc and startx),
01018b
then there's no process to handle reauthentication.
01018b
01018b
This commit notices that case, and creates a transient worker on the fly
01018b
just to perform one off authentication for unlock of non-GDM managed
01018b
sessions.
01018b
---
01018b
 daemon/Makefile.am   |  13 +++
01018b
 daemon/gdm-manager.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++++--
01018b
 2 files changed, 271 insertions(+), 10 deletions(-)
01018b
01018b
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
01018b
index ead9096..750735a 100644
01018b
--- a/daemon/Makefile.am
01018b
+++ b/daemon/Makefile.am
01018b
@@ -289,83 +289,96 @@ endif
01018b
 
01018b
 gdm_session_worker_LDFLAGS =			\
01018b
 	$(XLIB_LIBS)				\
01018b
 	$(PAM_LIBS)				\
01018b
 	$(NULL)
01018b
 
01018b
 gdm_session_worker_LDADD = 			\
01018b
 	$(top_builddir)/common/libgdmcommon.la	\
01018b
 	$(DAEMON_LIBS)				\
01018b
 	$(SYSTEMD_LIBS) 			\
01018b
 	$(JOURNALD_LIBS) 			\
01018b
 	$(LIBSELINUX_LIBS) 			\
01018b
 	$(NULL)
01018b
 
01018b
 sbin_PROGRAMS = 			\
01018b
 	gdm				\
01018b
 	$(NULL)
01018b
 
01018b
 gdm_SOURCES = 			\
01018b
 	main.c				\
01018b
 	gdm-display-access-file.c	\
01018b
 	gdm-display-access-file.h	\
01018b
 	gdm-display-store.c		\
01018b
 	gdm-display-store.h		\
01018b
 	gdm-display-factory.c		\
01018b
 	gdm-display-factory.h		\
01018b
 	gdm-local-display-factory.c	\
01018b
 	gdm-local-display-factory.h	\
01018b
 	gdm-display.c			\
01018b
 	gdm-display.h			\
01018b
+	gdm-session.c			\
01018b
+	gdm-session.h			\
01018b
+	gdm-session-record.c		\
01018b
+	gdm-session-record.h		\
01018b
+	gdm-session-worker-common.c	\
01018b
+	gdm-session-worker-common.h	\
01018b
+	gdm-session-worker-job.c	\
01018b
 	gdm-static-display.c		\
01018b
 	gdm-static-display.h		\
01018b
 	gdm-transient-display.c		\
01018b
 	gdm-transient-display.h		\
01018b
 	gdm-manager.c			\
01018b
 	gdm-manager.h			\
01018b
 	gdm-slave-proxy.c		\
01018b
 	gdm-slave-proxy.h		\
01018b
 	gdm-dbus-util.c			\
01018b
 	gdm-dbus-util.h			\
01018b
 	$(NULL)
01018b
 
01018b
 nodist_gdm_SOURCES = 			\
01018b
 	gdm-display-glue.h			\
01018b
 	gdm-display-glue.c			\
01018b
 	gdm-local-display-factory-glue.h	\
01018b
 	gdm-local-display-factory-glue.c	\
01018b
 	gdm-manager-glue.h			\
01018b
 	gdm-manager-glue.c			\
01018b
 	gdm-transient-display-glue.h		\
01018b
 	gdm-transient-display-glue.c		\
01018b
 	gdm-static-display-glue.h		\
01018b
 	gdm-static-display-glue.c		\
01018b
+	gdm-session-enum-types.c		\
01018b
+	gdm-session-enum-types.h		\
01018b
+	gdm-session-glue.c			\
01018b
+	gdm-session-glue.h			\
01018b
+	gdm-session-worker-glue.c		\
01018b
+	gdm-session-worker-glue.h		\
01018b
 	gdm-slave-glue.h			\
01018b
 	gdm-slave-glue.c			\
01018b
 	$(NULL)
01018b
 
01018b
 XDMCP_SOURCES =				\
01018b
 	gdm-xdmcp-display-factory.c	\
01018b
 	gdm-xdmcp-display-factory.h	\
01018b
 	gdm-xdmcp-display.c		\
01018b
 	gdm-xdmcp-display.h		\
01018b
 	gdm-xdmcp-greeter-display.c	\
01018b
 	gdm-xdmcp-greeter-display.h	\
01018b
 	gdm-xdmcp-chooser-display.c	\
01018b
 	gdm-xdmcp-chooser-display.h	\
01018b
 	$(NULL)
01018b
 
01018b
 XDMCP_nodist_SOURCES = 			\
01018b
 	gdm-xdmcp-display-glue.c	\
01018b
 	gdm-xdmcp-display-glue.h	\
01018b
 	gdm-xdmcp-chooser-slave-glue.c	\
01018b
 	gdm-xdmcp-chooser-slave-glue.h	\
01018b
 	$(NULL)
01018b
 
01018b
 if XDMCP_SUPPORT
01018b
 gdm_SOURCES += $(XDMCP_SOURCES)
01018b
 nodist_gdm_SOURCES += $(XDMCP_nodist_SOURCES)
01018b
 endif
01018b
 
01018b
 EXTRA_gdm_SOURCES = 	\
01018b
 	$(XDMCP_SOURCES)	\
01018b
 	$(NULL)
01018b
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
01018b
index 4c47045..7eb2172 100644
01018b
--- a/daemon/gdm-manager.c
01018b
+++ b/daemon/gdm-manager.c
01018b
@@ -16,60 +16,61 @@
01018b
  * along with this program; if not, write to the Free Software
01018b
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
01018b
  *
01018b
  */
01018b
 
01018b
 #include "config.h"
01018b
 
01018b
 #include <stdlib.h>
01018b
 #include <stdio.h>
01018b
 #include <fcntl.h>
01018b
 #include <unistd.h>
01018b
 #include <string.h>
01018b
 #include <signal.h>
01018b
 #include <sys/stat.h>
01018b
 #include <sys/types.h>
01018b
 
01018b
 #include <glib.h>
01018b
 #include <glib/gi18n.h>
01018b
 #include <glib/gstdio.h>
01018b
 #include <glib-object.h>
01018b
 
01018b
 #ifdef WITH_SYSTEMD
01018b
 #include <systemd/sd-login.h>
01018b
 #endif
01018b
 
01018b
 #include "gdm-common.h"
01018b
 
01018b
 #include "gdm-dbus-util.h"
01018b
 #include "gdm-manager.h"
01018b
 #include "gdm-manager-glue.h"
01018b
+#include "gdm-session.h"
01018b
 #include "gdm-display-store.h"
01018b
 #include "gdm-display-factory.h"
01018b
 #include "gdm-local-display-factory.h"
01018b
 #include "gdm-xdmcp-display-factory.h"
01018b
 
01018b
 #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
01018b
 
01018b
 #define GDM_DBUS_PATH             "/org/gnome/DisplayManager"
01018b
 #define GDM_MANAGER_PATH          GDM_DBUS_PATH "/Manager"
01018b
 #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
01018b
 
01018b
 struct GdmManagerPrivate
01018b
 {
01018b
         GdmDisplayStore        *display_store;
01018b
         GdmLocalDisplayFactory *local_factory;
01018b
 #ifdef HAVE_LIBXDMCP
01018b
         GdmXdmcpDisplayFactory *xdmcp_factory;
01018b
 #endif
01018b
         gboolean                xdmcp_enabled;
01018b
 
01018b
         gboolean                started;
01018b
         gboolean                wait_for_go;
01018b
         gboolean                no_console;
01018b
 
01018b
         GDBusProxy               *bus_proxy;
01018b
         GDBusConnection          *connection;
01018b
         GDBusObjectManagerServer *object_manager;
01018b
 };
01018b
 
01018b
 enum {
01018b
@@ -648,104 +649,351 @@ gdm_manager_handle_open_session (GdmDBusManager        *manager,
01018b
 
01018b
         sender = g_dbus_method_invocation_get_sender (invocation);
01018b
         connection = g_dbus_method_invocation_get_connection (invocation);
01018b
         get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, &pid, &uid, NULL, NULL);
01018b
 
01018b
         if (display == NULL) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("No session available"));
01018b
 
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         address = gdm_display_open_session_sync (display, pid, uid, NULL, &error);
01018b
 
01018b
         if (address == NULL) {
01018b
                 g_dbus_method_invocation_return_gerror (invocation, error);
01018b
                 g_error_free (error);
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager),
01018b
                                                 invocation,
01018b
                                                 address);
01018b
         g_free (address);
01018b
 
01018b
         return TRUE;
01018b
 }
01018b
 
01018b
+#ifdef WITH_SYSTEMD
01018b
+static gboolean
01018b
+unlock_systemd_session (GdmManager *manager,
01018b
+                        const char *ssid)
01018b
+{
01018b
+        GError *error = NULL;
01018b
+        GVariant *reply;
01018b
+
01018b
+        reply = g_dbus_connection_call_sync (manager->priv->connection,
01018b
+                                             "org.freedesktop.login1",
01018b
+                                             "/org/freedesktop/login1",
01018b
+                                             "org.freedesktop.login1.Manager",
01018b
+                                             "UnlockSession",
01018b
+                                             g_variant_new ("(s)", ssid),
01018b
+                                             NULL, /* expected reply */
01018b
+                                             G_DBUS_CALL_FLAGS_NONE,
01018b
+                                             -1,
01018b
+                                             NULL,
01018b
+                                             &error);
01018b
+        if (reply == NULL) {
01018b
+                g_debug ("GdmManager: logind 'UnlockSession' %s raised:\n %s\n\n",
01018b
+                         g_dbus_error_get_remote_error (error), error->message);
01018b
+                g_error_free (error);
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        g_variant_unref (reply);
01018b
+
01018b
+        return TRUE;
01018b
+}
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+static gboolean
01018b
+unlock_consolekit_session (GdmManager *manager,
01018b
+                           const char *ssid)
01018b
+{
01018b
+        GError *error = NULL;
01018b
+        GVariant *reply;
01018b
+
01018b
+        reply = g_dbus_connection_call_sync (manager->priv->connection,
01018b
+                                             "org.freedesktop.ConsoleKit",
01018b
+                                             ssid,
01018b
+                                             "org.freedesktop.ConsoleKit.Manager",
01018b
+                                             "Unlock",
01018b
+                                             NULL, /* parameters */
01018b
+                                             NULL, /* expected reply */
01018b
+                                             G_DBUS_CALL_FLAGS_NONE,
01018b
+                                             -1,
01018b
+                                             NULL,
01018b
+                                             &error);
01018b
+        if (reply == NULL) {
01018b
+                g_debug ("GdmSlave: ConsoleKit %s raised:\n %s\n\n",
01018b
+                         g_dbus_error_get_remote_error (error), error->message);
01018b
+                g_error_free (error);
01018b
+                return FALSE;
01018b
+        }
01018b
+
01018b
+        g_variant_unref (reply);
01018b
+
01018b
+        return TRUE;
01018b
+}
01018b
+#endif
01018b
+
01018b
+static void
01018b
+unlock_session (GdmManager *manager,
01018b
+                const char *ssid)
01018b
+{
01018b
+
01018b
+        g_debug ("GdmManager: Unlocking session %s", ssid);
01018b
+
01018b
+#ifdef WITH_SYSTEMD
01018b
+        if (LOGIND_RUNNING()) {
01018b
+                unlock_systemd_session (manager, ssid);
01018b
+                return;
01018b
+        }
01018b
+#endif
01018b
+
01018b
+#ifdef WITH_CONSOLE_KIT
01018b
+        unlock_consolekit_session (manager, ssid);
01018b
+#endif
01018b
+}
01018b
+static void
01018b
+on_reauthentication_client_connected (GdmSession              *session,
01018b
+                                      GCredentials            *credentials,
01018b
+                                      GPid                     pid_of_client,
01018b
+                                      GdmManager              *self)
01018b
+{
01018b
+        g_debug ("GdmManager: client connected to reauthentication server");
01018b
+}
01018b
+
01018b
+static void
01018b
+on_reauthentication_client_disconnected (GdmSession              *session,
01018b
+                                         GCredentials            *credentials,
01018b
+                                         GPid                     pid_of_client,
01018b
+                                         GdmManager              *self)
01018b
+{
01018b
+        g_debug ("GdmManger: client disconnected from reauthentication server");
01018b
+        gdm_session_close (session);
01018b
+        g_object_unref (session);
01018b
+}
01018b
+
01018b
+static void
01018b
+on_reauthentication_cancelled (GdmSession *session,
01018b
+                               GdmManager *self)
01018b
+{
01018b
+        g_debug ("GdmManager: client cancelled reauthentication request");
01018b
+        gdm_session_close (session);
01018b
+        g_object_unref (session);
01018b
+}
01018b
+
01018b
+static void
01018b
+on_reauthentication_conversation_started (GdmSession *session,
01018b
+                                          const char *service_name,
01018b
+                                          GdmManager *self)
01018b
+{
01018b
+        g_debug ("GdmManager: reauthentication service '%s' started",
01018b
+                 service_name);
01018b
+}
01018b
+
01018b
+static void
01018b
+on_reauthentication_conversation_stopped (GdmSession *session,
01018b
+                                          const char *service_name,
01018b
+                                          GdmManager *self)
01018b
+{
01018b
+        g_debug ("GdmManager: reauthentication service '%s' stopped",
01018b
+                 service_name);
01018b
+}
01018b
+
01018b
+static void
01018b
+on_reauthentication_verification_complete (GdmSession *session,
01018b
+                                           const char *service_name,
01018b
+                                           GdmManager *self)
01018b
+{
01018b
+        const char *session_id;
01018b
+        session_id = g_object_get_data (G_OBJECT (session), "caller-session-id");
01018b
+        g_debug ("GdmManager: reauthenticated user in unmanaged session '%s' with service '%s'",
01018b
+                 session_id, service_name);
01018b
+        unlock_session (self, session_id);
01018b
+        gdm_session_close (session);
01018b
+        g_object_unref (session);
01018b
+}
01018b
+
01018b
+static void
01018b
+remove_session_weak_refs (GdmManager *self,
01018b
+                          GdmSession *session)
01018b
+{
01018b
+        g_object_weak_unref (G_OBJECT (self),
01018b
+                             (GWeakNotify)
01018b
+                             gdm_session_close,
01018b
+                             session);
01018b
+        g_object_weak_unref (G_OBJECT (self),
01018b
+                             (GWeakNotify)
01018b
+                             g_object_unref,
01018b
+                             session);
01018b
+}
01018b
+
01018b
+static char *
01018b
+open_temporary_reauthentication_channel (GdmManager            *self,
01018b
+                                         char                  *seat_id,
01018b
+                                         char                  *session_id,
01018b
+                                         GPid                   pid,
01018b
+                                         uid_t                  uid,
01018b
+                                         gboolean               is_remote)
01018b
+{
01018b
+        GdmSession *session;
01018b
+        char **environment;
01018b
+        const char *display, *auth_file;
01018b
+        char *address;
01018b
+
01018b
+        /* Note we're just using a minimal environment here rather than the
01018b
+         * session's environment because the caller is unprivileged and the
01018b
+         * associated worker will be privileged */
01018b
+        environment = g_get_environ ();
01018b
+        display = "";
01018b
+        auth_file = "/dev/null";
01018b
+
01018b
+        session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE,
01018b
+                                   uid,
01018b
+                                   display,
01018b
+                                   NULL,
01018b
+                                   NULL,
01018b
+                                   seat_id,
01018b
+                                   auth_file,
01018b
+                                   is_remote == FALSE,
01018b
+                                   (const char * const *)
01018b
+                                   environment);
01018b
+        g_strfreev (environment);
01018b
+
01018b
+        g_object_set_data_full (G_OBJECT (session),
01018b
+                                "caller-session-id",
01018b
+                                g_strdup (session_id),
01018b
+                                (GDestroyNotify)
01018b
+                                g_free);
01018b
+        g_object_weak_ref (G_OBJECT (self),
01018b
+                           (GWeakNotify)
01018b
+                           gdm_session_close,
01018b
+                           session);
01018b
+        g_object_weak_ref (G_OBJECT (self),
01018b
+                           (GWeakNotify)
01018b
+                           g_object_unref,
01018b
+                           session);
01018b
+        g_object_weak_ref (G_OBJECT (session),
01018b
+                           (GWeakNotify)
01018b
+                           remove_session_weak_refs,
01018b
+                           self);
01018b
+
01018b
+        g_signal_connect (session,
01018b
+                          "client-connected",
01018b
+                          G_CALLBACK (on_reauthentication_client_connected),
01018b
+                          self);
01018b
+        g_signal_connect (session,
01018b
+                          "client-disconnected",
01018b
+                          G_CALLBACK (on_reauthentication_client_disconnected),
01018b
+                          self);
01018b
+        g_signal_connect (session,
01018b
+                          "cancelled",
01018b
+                          G_CALLBACK (on_reauthentication_cancelled),
01018b
+                          self);
01018b
+        g_signal_connect (session,
01018b
+                          "conversation-started",
01018b
+                          G_CALLBACK (on_reauthentication_conversation_started),
01018b
+                          self);
01018b
+        g_signal_connect (session,
01018b
+                          "conversation-stopped",
01018b
+                          G_CALLBACK (on_reauthentication_conversation_stopped),
01018b
+                          self);
01018b
+        g_signal_connect (session,
01018b
+                          "verification-complete",
01018b
+                          G_CALLBACK (on_reauthentication_verification_complete),
01018b
+                          self);
01018b
+
01018b
+        address = gdm_session_get_server_address (session);
01018b
+        return address;
01018b
+}
01018b
+
01018b
 static gboolean
01018b
 gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager,
01018b
                                                   GDBusMethodInvocation *invocation,
01018b
                                                   const char            *username)
01018b
 {
01018b
         GdmManager       *self = GDM_MANAGER (manager);
01018b
         const char       *sender = NULL;
01018b
         GError           *error = NULL;
01018b
         GDBusConnection  *connection;
01018b
         GdmDisplay       *display = NULL;
01018b
         char             *address;
01018b
+        char             *seat_id = NULL;
01018b
+        char             *session_id = NULL;
01018b
         GPid              pid = 0;
01018b
         uid_t             uid = (uid_t) -1;
01018b
         gboolean          is_login_screen = FALSE;
01018b
+        gboolean          is_remote = FALSE;
01018b
 
01018b
         g_debug ("GdmManager: trying to open reauthentication channel for user %s", username);
01018b
 
01018b
         sender = g_dbus_method_invocation_get_sender (invocation);
01018b
         connection = g_dbus_method_invocation_get_connection (invocation);
01018b
-        get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, &pid, &uid, &is_login_screen, NULL);
01018b
+        get_display_and_details_for_bus_sender (self, connection, sender, &display, &seat_id, &session_id, &pid, &uid, &is_login_screen, &is_remote);
01018b
 
01018b
         if (is_login_screen) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
                                                                _("Login screen not allow to open reauthentication channel"));
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
-        if (display == NULL) {
01018b
+        if (session_id == NULL || pid == 0 || uid == (uid_t) -1) {
01018b
                 g_dbus_method_invocation_return_error_literal (invocation,
01018b
                                                                G_DBUS_ERROR,
01018b
                                                                G_DBUS_ERROR_ACCESS_DENIED,
01018b
-                                                               _("No session available"));
01018b
-
01018b
+                                                               _("Could not retrieve details about caller"));
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
-        address = gdm_display_open_reauthentication_channel_sync (display,
01018b
-                                                                  username,
01018b
-                                                                  pid,
01018b
-                                                                  uid,
01018b
-                                                                  NULL,
01018b
-                                                                  &error);
01018b
+        if (display == NULL) {
01018b
+                address = open_temporary_reauthentication_channel (self,
01018b
+                                                                   seat_id,
01018b
+                                                                   session_id,
01018b
+                                                                   pid,
01018b
+                                                                   uid,
01018b
+                                                                   is_remote);
01018b
+        } else {
01018b
+                address = gdm_display_open_reauthentication_channel_sync (display,
01018b
+                                                                          username,
01018b
+                                                                          pid,
01018b
+                                                                          uid,
01018b
+                                                                          NULL,
01018b
+                                                                          &error);
01018b
+        }
01018b
 
01018b
         if (address == NULL) {
01018b
                 g_dbus_method_invocation_return_gerror (invocation, error);
01018b
                 g_error_free (error);
01018b
                 return TRUE;
01018b
         }
01018b
 
01018b
         gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
01018b
                                                                  invocation,
01018b
                                                                  address);
01018b
         g_free (address);
01018b
 
01018b
         return TRUE;
01018b
 }
01018b
 
01018b
 static void
01018b
 manager_interface_init (GdmDBusManagerIface *interface)
01018b
 {
01018b
         interface->handle_open_session = gdm_manager_handle_open_session;
01018b
         interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel;
01018b
 }
01018b
 
01018b
 static void
01018b
 on_display_removed (GdmDisplayStore *display_store,
01018b
                     const char      *id,
01018b
                     GdmManager      *manager)
01018b
 {
01018b
         GdmDisplay *display;
01018b
 
01018b
         display = gdm_display_store_lookup (display_store, id);
01018b
-- 
01018b
1.8.4.2
01018b
7ae91c
From a63ed886a5b232cc44938badd37daf394215d3b9 Mon Sep 17 00:00:00 2001
7ae91c
From: Ray Strode <rstrode@redhat.com>
7ae91c
Date: Thu, 10 Apr 2014 08:56:10 -0400
7ae91c
Subject: [PATCH 1/4] session: introduce new client-rejected signal
7ae91c
7ae91c
If a client gets rejected because it's not allowed to connect
7ae91c
to a particular session, we really need to inform the owner
7ae91c
of the session object so it can do any clean up it needs to do,
7ae91c
if necessary.
7ae91c
---
7ae91c
 daemon/gdm-session.c | 24 ++++++++++++++++++++++++
7ae91c
 daemon/gdm-session.h |  1 +
7ae91c
 2 files changed, 25 insertions(+)
7ae91c
7ae91c
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
7ae91c
index e24ec7c..044a57c 100644
7ae91c
--- a/daemon/gdm-session.c
7ae91c
+++ b/daemon/gdm-session.c
7ae91c
@@ -117,60 +117,61 @@ struct _GdmSessionPrivate
7ae91c
 
7ae91c
         uid_t                allowed_user;
7ae91c
 
7ae91c
         char                *fallback_session_name;
7ae91c
 
7ae91c
         GDBusServer         *worker_server;
7ae91c
         GDBusServer         *outside_server;
7ae91c
         GHashTable          *environment;
7ae91c
 };
7ae91c
 
7ae91c
 enum {
7ae91c
         PROP_0,
7ae91c
         PROP_VERIFICATION_MODE,
7ae91c
         PROP_ALLOWED_USER,
7ae91c
         PROP_DISPLAY_NAME,
7ae91c
         PROP_DISPLAY_HOSTNAME,
7ae91c
         PROP_DISPLAY_IS_LOCAL,
7ae91c
         PROP_DISPLAY_DEVICE,
7ae91c
         PROP_DISPLAY_SEAT_ID,
7ae91c
         PROP_DISPLAY_X11_AUTHORITY_FILE,
7ae91c
         PROP_USER_X11_AUTHORITY_FILE,
7ae91c
         PROP_CONVERSATION_ENVIRONMENT,
7ae91c
 };
7ae91c
 
7ae91c
 enum {
7ae91c
         CONVERSATION_STARTED = 0,
7ae91c
         CONVERSATION_STOPPED,
7ae91c
         SETUP_COMPLETE,
7ae91c
         CANCELLED,
7ae91c
         HOSTNAME_SELECTED,
7ae91c
+        CLIENT_REJECTED,
7ae91c
         CLIENT_CONNECTED,
7ae91c
         CLIENT_DISCONNECTED,
7ae91c
         CLIENT_READY_FOR_SESSION_TO_START,
7ae91c
         DISCONNECTED,
7ae91c
         VERIFICATION_COMPLETE,
7ae91c
         SESSION_OPENED,
7ae91c
         SESSION_STARTED,
7ae91c
         SESSION_START_FAILED,
7ae91c
         SESSION_EXITED,
7ae91c
         SESSION_DIED,
7ae91c
         REAUTHENTICATION_STARTED,
7ae91c
         REAUTHENTICATED,
7ae91c
         LAST_SIGNAL
7ae91c
 };
7ae91c
 
7ae91c
 static guint signals [LAST_SIGNAL] = { 0, };
7ae91c
 
7ae91c
 G_DEFINE_TYPE (GdmSession,
7ae91c
                gdm_session,
7ae91c
                G_TYPE_OBJECT);
7ae91c
 
7ae91c
 static GdmSessionConversation *
7ae91c
 find_conversation_by_name (GdmSession *self,
7ae91c
                            const char *service_name)
7ae91c
 {
7ae91c
         GdmSessionConversation *conversation;
7ae91c
 
7ae91c
         conversation = g_hash_table_lookup (self->priv->conversations, service_name);
7ae91c
 
7ae91c
         if (conversation == NULL) {
7ae91c
@@ -1561,68 +1562,78 @@ setup_worker_server (GdmSession *self)
7ae91c
 
7ae91c
         server = gdm_dbus_setup_private_server (observer, &error);
7ae91c
         g_object_unref (observer);
7ae91c
 
7ae91c
         if (server == NULL) {
7ae91c
                 g_warning ("Cannot create worker D-Bus server for the session: %s",
7ae91c
                            error->message);
7ae91c
                 return;
7ae91c
         }
7ae91c
 
7ae91c
         g_signal_connect_object (server,
7ae91c
                                  "new-connection",
7ae91c
                                  G_CALLBACK (handle_connection_from_worker),
7ae91c
                                  self,
7ae91c
                                  0);
7ae91c
         self->priv->worker_server = server;
7ae91c
 
7ae91c
         g_dbus_server_start (server);
7ae91c
 
7ae91c
         g_debug ("GdmSession: D-Bus server for workers listening on %s",
7ae91c
         g_dbus_server_get_client_address (self->priv->worker_server));
7ae91c
 }
7ae91c
 
7ae91c
 static gboolean
7ae91c
 allow_user_function (GDBusAuthObserver *observer,
7ae91c
                      GIOStream         *stream,
7ae91c
                      GCredentials      *credentials,
7ae91c
                      GdmSession        *self)
7ae91c
 {
7ae91c
         uid_t client_uid;
7ae91c
+        GPid  pid_of_client;
7ae91c
 
7ae91c
         client_uid = g_credentials_get_unix_user (credentials, NULL);
7ae91c
         if (client_uid == self->priv->allowed_user) {
7ae91c
                 return TRUE;
7ae91c
         }
7ae91c
 
7ae91c
         g_debug ("GdmSession: User not allowed");
7ae91c
 
7ae91c
+        pid_of_client = credentials_get_unix_pid (credentials);
7ae91c
+        g_signal_emit (G_OBJECT (self),
7ae91c
+                       signals [CLIENT_REJECTED],
7ae91c
+                       0,
7ae91c
+                       credentials,
7ae91c
+                       (guint)
7ae91c
+                       pid_of_client);
7ae91c
+
7ae91c
+
7ae91c
         return FALSE;
7ae91c
 }
7ae91c
 
7ae91c
 static void
7ae91c
 setup_outside_server (GdmSession *self)
7ae91c
 {
7ae91c
         GDBusAuthObserver *observer;
7ae91c
         GDBusServer *server;
7ae91c
         GError *error = NULL;
7ae91c
 
7ae91c
         g_debug ("GdmSession: Creating D-Bus server for greeters and such");
7ae91c
 
7ae91c
         observer = g_dbus_auth_observer_new ();
7ae91c
         g_signal_connect_object (observer,
7ae91c
                                  "authorize-authenticated-peer",
7ae91c
                                  G_CALLBACK (allow_user_function),
7ae91c
                                  self,
7ae91c
                                  0);
7ae91c
 
7ae91c
         server = gdm_dbus_setup_private_server (observer, &error);
7ae91c
         g_object_unref (observer);
7ae91c
 
7ae91c
         if (server == NULL) {
7ae91c
                 g_warning ("Cannot create greeter D-Bus server for the session: %s",
7ae91c
                            error->message);
7ae91c
                 return;
7ae91c
         }
7ae91c
 
7ae91c
         g_signal_connect_object (server,
7ae91c
                                  "new-connection",
7ae91c
@@ -3186,60 +3197,73 @@ gdm_session_class_init (GdmSessionClass *session_class)
7ae91c
                               G_STRUCT_OFFSET (GdmSessionClass, reauthentication_started),
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               G_TYPE_NONE,
7ae91c
                               2,
7ae91c
                               G_TYPE_INT,
7ae91c
                               G_TYPE_STRING);
7ae91c
         signals [REAUTHENTICATED] =
7ae91c
                 g_signal_new ("reauthenticated",
7ae91c
                               GDM_TYPE_SESSION,
7ae91c
                               G_SIGNAL_RUN_FIRST,
7ae91c
                               G_STRUCT_OFFSET (GdmSessionClass, reauthenticated),
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               G_TYPE_NONE,
7ae91c
                               1,
7ae91c
                               G_TYPE_STRING);
7ae91c
         signals [CANCELLED] =
7ae91c
                 g_signal_new ("cancelled",
7ae91c
                               GDM_TYPE_SESSION,
7ae91c
                               G_SIGNAL_RUN_FIRST,
7ae91c
                               G_STRUCT_OFFSET (GdmSessionClass, cancelled),
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               g_cclosure_marshal_VOID__VOID,
7ae91c
                               G_TYPE_NONE,
7ae91c
                               0);
7ae91c
 
7ae91c
+        signals [CLIENT_REJECTED] =
7ae91c
+                g_signal_new ("client-rejected",
7ae91c
+                              GDM_TYPE_SESSION,
7ae91c
+                              G_SIGNAL_RUN_FIRST,
7ae91c
+                              G_STRUCT_OFFSET (GdmSessionClass, client_rejected),
7ae91c
+                              NULL,
7ae91c
+                              NULL,
7ae91c
+                              NULL,
7ae91c
+                              G_TYPE_NONE,
7ae91c
+                              2,
7ae91c
+                              G_TYPE_CREDENTIALS,
7ae91c
+                              G_TYPE_UINT);
7ae91c
+
7ae91c
         signals [CLIENT_CONNECTED] =
7ae91c
                 g_signal_new ("client-connected",
7ae91c
                               GDM_TYPE_SESSION,
7ae91c
                               G_SIGNAL_RUN_FIRST,
7ae91c
                               G_STRUCT_OFFSET (GdmSessionClass, client_connected),
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               G_TYPE_NONE,
7ae91c
                               2,
7ae91c
                               G_TYPE_CREDENTIALS,
7ae91c
                               G_TYPE_UINT);
7ae91c
 
7ae91c
         signals [CLIENT_DISCONNECTED] =
7ae91c
                 g_signal_new ("client-disconnected",
7ae91c
                               GDM_TYPE_SESSION,
7ae91c
                               G_SIGNAL_RUN_FIRST,
7ae91c
                               G_STRUCT_OFFSET (GdmSessionClass, client_disconnected),
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               NULL,
7ae91c
                               G_TYPE_NONE,
7ae91c
                               2,
7ae91c
                               G_TYPE_CREDENTIALS,
7ae91c
                               G_TYPE_UINT);
7ae91c
         signals [CLIENT_READY_FOR_SESSION_TO_START] =
7ae91c
                 g_signal_new ("client-ready-for-session-to-start",
7ae91c
                               GDM_TYPE_SESSION,
7ae91c
                               G_SIGNAL_RUN_FIRST,
7ae91c
                               G_STRUCT_OFFSET (GdmSessionClass, client_ready_for_session_to_start),
7ae91c
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
7ae91c
index 2511eca..8b93e2c 100644
7ae91c
--- a/daemon/gdm-session.h
7ae91c
+++ b/daemon/gdm-session.h
7ae91c
@@ -30,60 +30,61 @@ G_BEGIN_DECLS
7ae91c
 #define GDM_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SESSION, GdmSessionClass))
7ae91c
 #define GDM_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SESSION))
7ae91c
 #define GDM_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION))
7ae91c
 #define GDM_SESSION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION, GdmSessionClass))
7ae91c
 
7ae91c
 typedef struct _GdmSessionPrivate GdmSessionPrivate;
7ae91c
 
7ae91c
 typedef enum
7ae91c
 {
7ae91c
         GDM_SESSION_VERIFICATION_MODE_LOGIN,
7ae91c
         GDM_SESSION_VERIFICATION_MODE_CHOOSER,
7ae91c
         GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE
7ae91c
 } GdmSessionVerificationMode;
7ae91c
 
7ae91c
 typedef struct
7ae91c
 {
7ae91c
         GObject            parent;
7ae91c
         GdmSessionPrivate *priv;
7ae91c
 } GdmSession;
7ae91c
 
7ae91c
 typedef struct
7ae91c
 {
7ae91c
         GObjectClass parent_class;
7ae91c
 
7ae91c
         /* Signals */
7ae91c
         void (* client_ready_for_session_to_start) (GdmSession   *session,
7ae91c
                                                     const char   *service_name,
7ae91c
                                                     gboolean      client_is_ready);
7ae91c
 
7ae91c
         void (* cancelled)                   (GdmSession   *session);
7ae91c
+        void (* client_rejected)             (GdmSession   *session);
7ae91c
         void (* client_connected)            (GdmSession   *session);
7ae91c
         void (* client_disconnected)         (GdmSession   *session);
7ae91c
         void (* disconnected)                (GdmSession   *session);
7ae91c
         void (* verification_complete)       (GdmSession   *session,
7ae91c
                                               const char   *service_name);
7ae91c
         void (* session_opened)              (GdmSession   *session,
7ae91c
                                               const char   *service_name,
7ae91c
                                               const char   *session_id);
7ae91c
         void (* session_started)             (GdmSession   *session,
7ae91c
                                               const char   *service_name,
7ae91c
                                               const char   *session_id,
7ae91c
                                               int           pid);
7ae91c
         void (* session_start_failed)        (GdmSession   *session,
7ae91c
                                               const char   *service_name,
7ae91c
                                               const char   *message);
7ae91c
         void (* session_exited)              (GdmSession   *session,
7ae91c
                                               int           exit_code);
7ae91c
         void (* session_died)                (GdmSession   *session,
7ae91c
                                               int           signal_number);
7ae91c
         void (* reauthentication_started)    (GdmSession   *session,
7ae91c
                                               GPid          pid_of_caller);
7ae91c
         void (* reauthenticated)             (GdmSession   *session,
7ae91c
                                               const char   *service_name);
7ae91c
         void (* conversation_started)        (GdmSession   *session,
7ae91c
                                               const char   *service_name);
7ae91c
         void (* conversation_stopped)        (GdmSession   *session,
7ae91c
                                               const char   *service_name);
7ae91c
         void (* setup_complete)              (GdmSession   *session,
7ae91c
                                               const char   *service_name);
7ae91c
 } GdmSessionClass;
7ae91c
-- 
7ae91c
1.9.0
7ae91c
7ae91c
7ae91c
From d11dd2511e08ab73757b8e97572c912c1f2fff8d Mon Sep 17 00:00:00 2001
7ae91c
From: Ray Strode <rstrode@redhat.com>
7ae91c
Date: Thu, 10 Apr 2014 09:13:57 -0400
7ae91c
Subject: [PATCH 2/4] manager: stuff pid associated with transient session on
7ae91c
 session object
7ae91c
7ae91c
In the event the session object is not associated with an audit session,
7ae91c
we want some way to match the object back to a client. This commit
7ae91c
stores the pid of the caller on the object.
7ae91c
---
7ae91c
 daemon/gdm-manager.c | 3 +++
7ae91c
 1 file changed, 3 insertions(+)
7ae91c
7ae91c
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
7ae91c
index e6fd0b4..4d60ac0 100644
7ae91c
--- a/daemon/gdm-manager.c
7ae91c
+++ b/daemon/gdm-manager.c
7ae91c
@@ -843,60 +843,63 @@ open_temporary_reauthentication_channel (GdmManager            *self,
7ae91c
 {
7ae91c
         GdmSession *session;
7ae91c
         char **environment;
7ae91c
         const char *display, *auth_file;
7ae91c
         char *address;
7ae91c
 
7ae91c
         /* Note we're just using a minimal environment here rather than the
7ae91c
          * session's environment because the caller is unprivileged and the
7ae91c
          * associated worker will be privileged */
7ae91c
         environment = g_get_environ ();
7ae91c
         display = "";
7ae91c
         auth_file = "/dev/null";
7ae91c
 
7ae91c
         session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE,
7ae91c
                                    uid,
7ae91c
                                    display,
7ae91c
                                    NULL,
7ae91c
                                    NULL,
7ae91c
                                    seat_id,
7ae91c
                                    auth_file,
7ae91c
                                    is_remote == FALSE,
7ae91c
                                    (const char * const *)
7ae91c
                                    environment);
7ae91c
         g_strfreev (environment);
7ae91c
 
7ae91c
         g_object_set_data_full (G_OBJECT (session),
7ae91c
                                 "caller-session-id",
7ae91c
                                 g_strdup (session_id),
7ae91c
                                 (GDestroyNotify)
7ae91c
                                 g_free);
7ae91c
+        g_object_set_data (G_OBJECT (session),
7ae91c
+                           "caller-pid",
7ae91c
+                           GINT_TO_POINTER ((gint) pid));
7ae91c
         g_object_weak_ref (G_OBJECT (self),
7ae91c
                            (GWeakNotify)
7ae91c
                            gdm_session_close,
7ae91c
                            session);
7ae91c
         g_object_weak_ref (G_OBJECT (self),
7ae91c
                            (GWeakNotify)
7ae91c
                            g_object_unref,
7ae91c
                            session);
7ae91c
         g_object_weak_ref (G_OBJECT (session),
7ae91c
                            (GWeakNotify)
7ae91c
                            remove_session_weak_refs,
7ae91c
                            self);
7ae91c
 
7ae91c
         g_signal_connect (session,
7ae91c
                           "client-connected",
7ae91c
                           G_CALLBACK (on_reauthentication_client_connected),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "client-disconnected",
7ae91c
                           G_CALLBACK (on_reauthentication_client_disconnected),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "cancelled",
7ae91c
                           G_CALLBACK (on_reauthentication_cancelled),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "conversation-started",
7ae91c
                           G_CALLBACK (on_reauthentication_conversation_started),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
-- 
7ae91c
1.9.0
7ae91c
7ae91c
7ae91c
From 24c3d14d5336aa59d15f1cfdb59643dd254a62bd Mon Sep 17 00:00:00 2001
7ae91c
From: Ray Strode <rstrode@redhat.com>
7ae91c
Date: Thu, 10 Apr 2014 09:22:07 -0400
7ae91c
Subject: [PATCH 3/4] manager: don't leak session objects when client is
7ae91c
 rejected
7ae91c
7ae91c
if a client creates a transient reauthentication session and then we reject
7ae91c
the client when it tries to connect to it, then we need to clean up
7ae91c
the associated session object.
7ae91c
7ae91c
This commit does that.
7ae91c
---
7ae91c
 daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
7ae91c
 1 file changed, 46 insertions(+)
7ae91c
7ae91c
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
7ae91c
index 4d60ac0..084fbb4 100644
7ae91c
--- a/daemon/gdm-manager.c
7ae91c
+++ b/daemon/gdm-manager.c
7ae91c
@@ -752,60 +752,102 @@ unlock_session (GdmManager *manager,
7ae91c
                 unlock_systemd_session (manager, ssid);
7ae91c
                 return;
7ae91c
         }
7ae91c
 #endif
7ae91c
 
7ae91c
 #ifdef WITH_CONSOLE_KIT
7ae91c
         unlock_consolekit_session (manager, ssid);
7ae91c
 #endif
7ae91c
 }
7ae91c
 static void
7ae91c
 on_reauthentication_client_connected (GdmSession              *session,
7ae91c
                                       GCredentials            *credentials,
7ae91c
                                       GPid                     pid_of_client,
7ae91c
                                       GdmManager              *self)
7ae91c
 {
7ae91c
         g_debug ("GdmManager: client connected to reauthentication server");
7ae91c
 }
7ae91c
 
7ae91c
 static void
7ae91c
 on_reauthentication_client_disconnected (GdmSession              *session,
7ae91c
                                          GCredentials            *credentials,
7ae91c
                                          GPid                     pid_of_client,
7ae91c
                                          GdmManager              *self)
7ae91c
 {
7ae91c
         g_debug ("GdmManger: client disconnected from reauthentication server");
7ae91c
         gdm_session_close (session);
7ae91c
         g_object_unref (session);
7ae91c
 }
7ae91c
 
7ae91c
 static void
7ae91c
+on_reauthentication_client_rejected (GdmSession              *session,
7ae91c
+                                     GCredentials            *credentials,
7ae91c
+                                     GPid                     pid_of_client,
7ae91c
+                                     GdmManager              *self)
7ae91c
+{
7ae91c
+        GPid pid;
7ae91c
+
7ae91c
+        g_debug ("GdmManger: client with pid %ld rejected from reauthentication server", (long) pid_of_client);
7ae91c
+
7ae91c
+        if (gdm_session_client_is_connected (session)) {
7ae91c
+                /* we already have a client connected, ignore this rejected one */
7ae91c
+                return;
7ae91c
+        }
7ae91c
+
7ae91c
+        pid = (GPid) GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "caller-pid"));
7ae91c
+
7ae91c
+        if (pid != pid_of_client) {
7ae91c
+                const char *session_id;
7ae91c
+                char *client_session_id;
7ae91c
+
7ae91c
+                /* rejected client isn't the process that started the
7ae91c
+                 * transient reauthentication session. If it's not even from the
7ae91c
+                 * same audit session, ignore it since it doesn't "own" the
7ae91c
+                 * reauthentication session
7ae91c
+                 */
7ae91c
+                client_session_id = get_session_id_for_pid (self->priv->connection,
7ae91c
+                                                            pid_of_client,
7ae91c
+                                                            NULL);
7ae91c
+                session_id = g_object_get_data (G_OBJECT (session), "caller-session-id");
7ae91c
+
7ae91c
+                if (g_strcmp0 (session_id, client_session_id) != 0) {
7ae91c
+                        return;
7ae91c
+                }
7ae91c
+        }
7ae91c
+
7ae91c
+        /* client was rejected, so clean up its session object
7ae91c
+         */
7ae91c
+        gdm_session_close (session);
7ae91c
+        g_object_unref (session);
7ae91c
+}
7ae91c
+
7ae91c
+static void
7ae91c
 on_reauthentication_cancelled (GdmSession *session,
7ae91c
                                GdmManager *self)
7ae91c
 {
7ae91c
         g_debug ("GdmManager: client cancelled reauthentication request");
7ae91c
         gdm_session_close (session);
7ae91c
         g_object_unref (session);
7ae91c
 }
7ae91c
 
7ae91c
 static void
7ae91c
 on_reauthentication_conversation_started (GdmSession *session,
7ae91c
                                           const char *service_name,
7ae91c
                                           GdmManager *self)
7ae91c
 {
7ae91c
         g_debug ("GdmManager: reauthentication service '%s' started",
7ae91c
                  service_name);
7ae91c
 }
7ae91c
 
7ae91c
 static void
7ae91c
 on_reauthentication_conversation_stopped (GdmSession *session,
7ae91c
                                           const char *service_name,
7ae91c
                                           GdmManager *self)
7ae91c
 {
7ae91c
         g_debug ("GdmManager: reauthentication service '%s' stopped",
7ae91c
                  service_name);
7ae91c
 }
7ae91c
 
7ae91c
 static void
7ae91c
 on_reauthentication_verification_complete (GdmSession *session,
7ae91c
                                            const char *service_name,
7ae91c
                                            GdmManager *self)
7ae91c
@@ -868,60 +910,64 @@ open_temporary_reauthentication_channel (GdmManager            *self,
7ae91c
         g_object_set_data_full (G_OBJECT (session),
7ae91c
                                 "caller-session-id",
7ae91c
                                 g_strdup (session_id),
7ae91c
                                 (GDestroyNotify)
7ae91c
                                 g_free);
7ae91c
         g_object_set_data (G_OBJECT (session),
7ae91c
                            "caller-pid",
7ae91c
                            GINT_TO_POINTER ((gint) pid));
7ae91c
         g_object_weak_ref (G_OBJECT (self),
7ae91c
                            (GWeakNotify)
7ae91c
                            gdm_session_close,
7ae91c
                            session);
7ae91c
         g_object_weak_ref (G_OBJECT (self),
7ae91c
                            (GWeakNotify)
7ae91c
                            g_object_unref,
7ae91c
                            session);
7ae91c
         g_object_weak_ref (G_OBJECT (session),
7ae91c
                            (GWeakNotify)
7ae91c
                            remove_session_weak_refs,
7ae91c
                            self);
7ae91c
 
7ae91c
         g_signal_connect (session,
7ae91c
                           "client-connected",
7ae91c
                           G_CALLBACK (on_reauthentication_client_connected),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "client-disconnected",
7ae91c
                           G_CALLBACK (on_reauthentication_client_disconnected),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
+                          "client-rejected",
7ae91c
+                          G_CALLBACK (on_reauthentication_client_rejected),
7ae91c
+                          self);
7ae91c
+        g_signal_connect (session,
7ae91c
                           "cancelled",
7ae91c
                           G_CALLBACK (on_reauthentication_cancelled),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "conversation-started",
7ae91c
                           G_CALLBACK (on_reauthentication_conversation_started),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "conversation-stopped",
7ae91c
                           G_CALLBACK (on_reauthentication_conversation_stopped),
7ae91c
                           self);
7ae91c
         g_signal_connect (session,
7ae91c
                           "verification-complete",
7ae91c
                           G_CALLBACK (on_reauthentication_verification_complete),
7ae91c
                           self);
7ae91c
 
7ae91c
         address = gdm_session_get_server_address (session);
7ae91c
         return address;
7ae91c
 }
7ae91c
 
7ae91c
 static gboolean
7ae91c
 gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager,
7ae91c
                                                   GDBusMethodInvocation *invocation,
7ae91c
                                                   const char            *username)
7ae91c
 {
7ae91c
         GdmManager       *self = GDM_MANAGER (manager);
7ae91c
         const char       *sender = NULL;
7ae91c
         GError           *error = NULL;
7ae91c
         GDBusConnection  *connection;
7ae91c
         GdmDisplay       *display = NULL;
7ae91c
-- 
7ae91c
1.9.0
7ae91c
7ae91c
7ae91c
From 9d67a7fd3acdc4b063020dfca53f676c2f1449d1 Mon Sep 17 00:00:00 2001
7ae91c
From: Ray Strode <rstrode@redhat.com>
7ae91c
Date: Thu, 10 Apr 2014 09:27:59 -0400
7ae91c
Subject: [PATCH 4/4] manager: be more accepting of callers with uids different
7ae91c
 from their session
7ae91c
7ae91c
If a user runs su in their session, that switched user will now be
7ae91c
running in a session that doesn't belong to it.  GDM won't allow a user
7ae91c
access to the worker process associated with the session in this case.
7ae91c
Instead, it will try to create a temporary just-in-time reauthentication
7ae91c
channel so reauthentication can happen without having the user talking to
7ae91c
another user's worker. Unfortunately, a logic error in the code means,
7ae91c
the user won't access to its own just-in-time channel.
7ae91c
7ae91c
This commit fixes that.
7ae91c
---
7ae91c
 daemon/gdm-manager.c | 2 +-
7ae91c
 1 file changed, 1 insertion(+), 1 deletion(-)
7ae91c
7ae91c
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
7ae91c
index 084fbb4..5809792 100644
7ae91c
--- a/daemon/gdm-manager.c
7ae91c
+++ b/daemon/gdm-manager.c
7ae91c
@@ -568,61 +568,61 @@ get_display_and_details_for_bus_sender (GdmManager       *self,
7ae91c
         if (session_id == NULL) {
7ae91c
                 g_debug ("GdmManager: Error while retrieving session id for sender: %s",
7ae91c
                          error->message);
7ae91c
                 g_error_free (error);
7ae91c
                 goto out;
7ae91c
         }
7ae91c
 
7ae91c
         if (out_session_id != NULL) {
7ae91c
                 *out_session_id = g_strdup (session_id);
7ae91c
         }
7ae91c
 
7ae91c
         if (out_is_login_screen != NULL) {
7ae91c
                 *out_is_login_screen = is_login_session (self, connection, session_id, &error);
7ae91c
 
7ae91c
                 if (error != NULL) {
7ae91c
                         g_debug ("GdmManager: Error while checking if sender is login screen: %s",
7ae91c
                                  error->message);
7ae91c
                         g_error_free (error);
7ae91c
                         goto out;
7ae91c
                 }
7ae91c
         }
7ae91c
 
7ae91c
         if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) {
7ae91c
                 g_debug ("GdmManager: Error while retrieving uid for session: %s",
7ae91c
                          error->message);
7ae91c
                 g_error_free (error);
7ae91c
                 goto out;
7ae91c
         }
7ae91c
 
7ae91c
         if (out_uid != NULL)
7ae91c
-            *out_uid = session_uid;
7ae91c
+            *out_uid = caller_uid;
7ae91c
 
7ae91c
         if (caller_uid != session_uid) {
7ae91c
                 g_debug ("GdmManager: uid for sender and uid for session don't match");
7ae91c
                 goto out;
7ae91c
         }
7ae91c
 
7ae91c
         if (out_seat_id != NULL) {
7ae91c
                 *out_seat_id = get_seat_id_for_session_id (connection, session_id, &error);
7ae91c
 
7ae91c
                 if (error != NULL) {
7ae91c
                         g_debug ("GdmManager: Error while retrieving seat id for session: %s",
7ae91c
                                  error->message);
7ae91c
                         g_clear_error (&error);
7ae91c
                 }
7ae91c
         }
7ae91c
 
7ae91c
         if (out_is_remote != NULL) {
7ae91c
                 *out_is_remote = is_remote_session (self, connection, session_id, &error);
7ae91c
 
7ae91c
                 if (error != NULL) {
7ae91c
                         g_debug ("GdmManager: Error while retrieving remoteness for session: %s",
7ae91c
                                  error->message);
7ae91c
                         g_clear_error (&error);
7ae91c
                 }
7ae91c
         }
7ae91c
 
7ae91c
         display = gdm_display_store_find (self->priv->display_store,
7ae91c
                                           lookup_by_session_id,
7ae91c
                                           (gpointer) session_id);
7ae91c
         if (out_display != NULL)
7ae91c
-- 
7ae91c
1.9.0
7ae91c