summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2012-07-17 14:26:18 -0400
committerJasper St. Pierre <jstpierre@mecheye.net>2012-08-01 12:16:36 -0300
commit67235fd797e5b9a88178f4733551814b61a4711b (patch)
treedf9b7f50110979912ed5fe5a4095b18b3eb1a73b /daemon
parent2672f6a1f43d054c0aab34b623f0f0e6edd8ed5f (diff)
downloadgdm-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.c33
-rw-r--r--daemon/gdm-session-worker.xml3
-rw-r--r--daemon/gdm-session.c34
-rw-r--r--daemon/gdm-session.xml4
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>