[gdm] daemon: Provide mechanism for providing an authentication secret up front



commit 67235fd797e5b9a88178f4733551814b61a4711b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Jul 17 14:26:18 2012 -0400

    daemon: Provide mechanism for providing an authentication secret up front
    
    Some PAM modules can be told their password ahead of time to prevent them
    having to ask later. This is accomplished by setting the PAM_AUTHTOK item
    before calling pam_authenticate.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=678057

 daemon/gdm-session-worker.c   |   33 +++++++++++++++++++++++++++++++++
 daemon/gdm-session-worker.xml |    3 +++
 daemon/gdm-session.c          |   34 ++++++++++++++++++++++++++++++++++
 daemon/gdm-session.xml        |    4 ++++
 4 files changed, 74 insertions(+), 0 deletions(-)
---
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index a422bb7..afa0466 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -2708,6 +2708,38 @@ reauthentication_request_new (GdmSessionWorker      *worker,
 }
 
 static gboolean
+gdm_session_worker_handle_set_initial_secret (GdmDBusWorker         *object,
+                                              GDBusMethodInvocation *invocation,
+                                              const char            *initial_secret)
+{
+        GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
+        int error_code;
+
+        if (worker->priv->state != GDM_SESSION_WORKER_STATE_SETUP_COMPLETE) {
+                g_dbus_method_invocation_return_error (invocation,
+                                                       GDM_SESSION_WORKER_ERROR,
+                                                       GDM_SESSION_WORKER_ERROR_WRONG_STATE,
+                                                       "Cannot set iniital secret while in state %s",
+                                                       get_state_name (worker->priv->state));
+                goto out;
+        }
+
+        error_code = pam_set_item (worker->priv->pam_handle, PAM_AUTHTOK, initial_secret);
+
+        if (error_code != PAM_SUCCESS) {
+                g_dbus_method_invocation_return_error (invocation,
+                                                       GDM_SESSION_WORKER_ERROR,
+                                                       GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
+                                                       "Error informing authentication system of user's authtok: %s",
+                                                       pam_strerror (worker->priv->pam_handle, error_code));
+                goto out;
+        }
+
+ out:
+        return TRUE;
+}
+
+static gboolean
 gdm_session_worker_handle_start_reauthentication (GdmDBusWorker         *object,
                                                   GDBusMethodInvocation *invocation,
                                                   int                    pid_of_caller,
@@ -2810,6 +2842,7 @@ worker_interface_init (GdmDBusWorkerIface *interface)
         interface->handle_set_environment_variable = gdm_session_worker_handle_set_environment_variable;
         interface->handle_start_program = gdm_session_worker_handle_start_program;
         interface->handle_start_reauthentication = gdm_session_worker_handle_start_reauthentication;
+        interface->handle_set_initial_secret = gdm_session_worker_handle_set_initial_secret;
 }
 
 static void
diff --git a/daemon/gdm-session-worker.xml b/daemon/gdm-session-worker.xml
index 990a133..97e4945 100644
--- a/daemon/gdm-session-worker.xml
+++ b/daemon/gdm-session-worker.xml
@@ -59,6 +59,9 @@
       <arg name="uid_of_caller" direction="in" type="i"/>
       <arg name="address" direction="out" type="s"/>
     </method>
+    <method name="SetInitialSecret">
+      <arg name="initial_secret" direction="in" type="s"/>
+    </method>
 
     <signal name="SessionExited">
       <arg name="service_name" type="s" />
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index f72c808..81a41d3 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -78,6 +78,7 @@ typedef struct
         GDBusConnection       *worker_connection;
         GDBusMethodInvocation *starting_invocation;
         char                  *starting_username;
+        char                  *starting_secret;
         GDBusMethodInvocation *pending_invocation;
         GdmDBusWorkerManager  *worker_manager_interface;
         GdmDBusWorker         *worker_proxy;
@@ -1051,6 +1052,13 @@ register_worker (GdmDBusWorkerManager  *worker_manager_interface,
         }
 
         if (conversation->starting_invocation != NULL) {
+                if (conversation->starting_secret != NULL) {
+                        gdm_dbus_worker_call_set_initial_secret (conversation->worker_proxy,
+                                                                 conversation->starting_secret,
+                                                                 NULL, NULL, NULL);
+                        g_clear_pointer (&conversation->starting_secret, (GDestroyNotify) g_free);
+                }
+
                 if (conversation->starting_username != NULL) {
                         gdm_session_setup_for_user (self, conversation->service_name, conversation->starting_username);
 
@@ -1199,6 +1207,27 @@ gdm_session_handle_client_begin_verification_for_user (GdmDBusUserVerifier    *u
 }
 
 static gboolean
+gdm_session_handle_client_begin_verification_for_user_with_secret (GdmDBusUserVerifier   *user_verifier_interface,
+                                                                   GDBusMethodInvocation *invocation,
+                                                                   const char            *service_name,
+                                                                   const char            *username,
+                                                                   const char            *secret,
+                                                                   GdmSession            *self)
+{
+        GdmSessionConversation *conversation;
+
+        conversation = begin_verification_conversation (self, invocation, service_name);
+
+        if (conversation != NULL) {
+                conversation->starting_invocation = g_object_ref (invocation);
+                conversation->starting_username = g_strdup (username);
+                conversation->starting_secret = g_strdup (secret);
+        }
+
+        return TRUE;
+}
+
+static gboolean
 gdm_session_handle_client_answer_query (GdmDBusUserVerifier    *user_verifier_interface,
                                         GDBusMethodInvocation  *invocation,
                                         const char             *service_name,
@@ -1317,6 +1346,10 @@ export_user_verifier_interface (GdmSession      *self,
                           G_CALLBACK (gdm_session_handle_client_begin_verification_for_user),
                           self);
         g_signal_connect (user_verifier_interface,
+                          "handle-begin-verification-for-user-with-secret",
+                          G_CALLBACK (gdm_session_handle_client_begin_verification_for_user_with_secret),
+                          self);
+        g_signal_connect (user_verifier_interface,
                           "handle-answer-query",
                           G_CALLBACK (gdm_session_handle_client_answer_query),
                           self);
@@ -1618,6 +1651,7 @@ free_conversation (GdmSessionConversation *conversation)
         g_free (conversation->service_name);
         g_free (conversation->starting_username);
         g_free (conversation->session_id);
+        g_free (conversation->starting_secret);
         g_clear_object (&conversation->session);
         g_free (conversation);
 }
diff --git a/daemon/gdm-session.xml b/daemon/gdm-session.xml
index cf3103a..22b67dc 100644
--- a/daemon/gdm-session.xml
+++ b/daemon/gdm-session.xml
@@ -37,6 +37,10 @@
     </method>
     <method name="Cancel">
     </method>
+    <method name="SetInitialSecret">
+      <arg name="service_name" direction="in" type="s"/>
+      <arg name="initial_secret" direction="in" type="s"/>
+    </method>
     <signal name="ConversationStarted">
       <arg name="service_name" type="s"/>
     </signal>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]