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