diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2012-07-17 14:26:18 -0400 |
---|---|---|
committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2012-08-01 12:16:36 -0300 |
commit | 67235fd797e5b9a88178f4733551814b61a4711b (patch) | |
tree | df9b7f50110979912ed5fe5a4095b18b3eb1a73b /daemon | |
parent | 2672f6a1f43d054c0aab34b623f0f0e6edd8ed5f (diff) | |
download | gdm-67235fd797e5b9a88178f4733551814b61a4711b.tar.gz |
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
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/gdm-session-worker.c | 33 | ||||
-rw-r--r-- | daemon/gdm-session-worker.xml | 3 | ||||
-rw-r--r-- | daemon/gdm-session.c | 34 | ||||
-rw-r--r-- | 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 a422bb79..afa04667 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 990a1337..97e4945a 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 f72c8084..81a41d38 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 cf3103ac..22b67dcf 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> |