[gdm] Add ability to retry login on failures
- From: William Jon McCann <mccann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdm] Add ability to retry login on failures
- Date: Tue, 22 Jun 2010 02:44:42 +0000 (UTC)
commit 378ed9c6423a801f552fdf8ff774f6b2b6b09897
Author: William Jon McCann <jmccann redhat com>
Date: Mon Jun 21 19:00:27 2010 -0400
Add ability to retry login on failures
https://bugzilla.gnome.org/show_bug.cgi?id=622326
daemon/gdm-greeter-server.c | 9 ++
daemon/gdm-greeter-server.h | 1 +
daemon/gdm-simple-slave.c | 32 +++++-
gui/simple-greeter/gdm-greeter-client.c | 24 ++++
gui/simple-greeter/gdm-greeter-client.h | 1 +
gui/simple-greeter/gdm-greeter-login-window.c | 156 ++++++++++++++++--------
gui/simple-greeter/gdm-greeter-login-window.h | 1 +
gui/simple-greeter/gdm-greeter-session.c | 33 +++++
8 files changed, 204 insertions(+), 53 deletions(-)
---
diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c
index cecce83..b9d3b2e 100644
--- a/daemon/gdm-greeter-server.c
+++ b/daemon/gdm-greeter-server.c
@@ -239,6 +239,13 @@ gdm_greeter_server_problem (GdmGreeterServer *greeter_server,
}
gboolean
+gdm_greeter_server_authentication_failed (GdmGreeterServer *greeter_server)
+{
+ send_dbus_void_signal (greeter_server, "AuthenticationFailed");
+ return TRUE;
+}
+
+gboolean
gdm_greeter_server_reset (GdmGreeterServer *greeter_server)
{
send_dbus_void_signal (greeter_server, "Reset");
@@ -762,6 +769,8 @@ do_introspect (DBusConnection *connection,
" </signal>\n"
" <signal name=\"Reset\">\n"
" </signal>\n"
+ " <signal name=\"AuthenticationFailed\">\n"
+ " </signal>\n"
" <signal name=\"UserAuthorized\">\n"
" </signal>\n"
" </interface>\n");
diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h
index 6e92100..f9c157f 100644
--- a/daemon/gdm-greeter-server.h
+++ b/daemon/gdm-greeter-server.h
@@ -84,6 +84,7 @@ gboolean gdm_greeter_server_info (GdmGreeterServer *
const char *text);
gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server,
const char *text);
+gboolean gdm_greeter_server_authentication_failed (GdmGreeterServer *greeter_server);
gboolean gdm_greeter_server_reset (GdmGreeterServer *greeter_server);
gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server);
void gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server,
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 1fb5773..e370ba9 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -204,6 +204,22 @@ greeter_reset_timeout (GdmSimpleSlave *slave)
return FALSE;
}
+static gboolean
+auth_failed_reset_timeout (GdmSimpleSlave *slave)
+{
+ g_debug ("GdmSimpleSlave: auth failed resetting slave");
+
+ if (slave->priv->greeter_server != NULL) {
+ gdm_greeter_server_authentication_failed (slave->priv->greeter_server);
+ reset_session (slave);
+ } else {
+ start_greeter (slave);
+ create_new_session (slave);
+ }
+ slave->priv->greeter_reset_id = 0;
+ return FALSE;
+}
+
static void
queue_greeter_reset (GdmSimpleSlave *slave)
{
@@ -215,6 +231,17 @@ queue_greeter_reset (GdmSimpleSlave *slave)
}
static void
+queue_auth_failed_reset (GdmSimpleSlave *slave)
+{
+ /* use the greeter reset idle id so we don't do both at once */
+ if (slave->priv->greeter_reset_id > 0) {
+ return;
+ }
+
+ slave->priv->greeter_reset_id = g_idle_add ((GSourceFunc)auth_failed_reset_timeout, slave);
+}
+
+static void
on_session_setup_complete (GdmSession *session,
GdmSimpleSlave *slave)
{
@@ -266,8 +293,11 @@ on_session_authentication_failed (GdmSession *session,
gdm_greeter_server_problem (slave->priv->greeter_server,
message != NULL ? message : _("Unable to authenticate user"));
}
+
destroy_session (slave);
- queue_greeter_reset (slave);
+
+ g_debug ("GdmSimpleSlave: Authentication failed - may retry");
+ queue_auth_failed_reset (slave);
}
static void
diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c
index ed4dd95..d02b3d1 100644
--- a/gui/simple-greeter/gdm-greeter-client.c
+++ b/gui/simple-greeter/gdm-greeter-client.c
@@ -65,6 +65,7 @@ enum {
SECRET_INFO_QUERY,
READY,
RESET,
+ AUTHENTICATION_FAILED,
SELECTED_USER_CHANGED,
DEFAULT_LANGUAGE_NAME_CHANGED,
DEFAULT_LAYOUT_NAME_CHANGED,
@@ -255,6 +256,17 @@ on_reset (GdmGreeterClient *client,
0);
}
+static void
+on_authentication_failed (GdmGreeterClient *client,
+ DBusMessage *message)
+{
+ g_debug ("GdmGreeterClient: Authentication failed");
+
+ g_signal_emit (client,
+ gdm_greeter_client_signals[AUTHENTICATION_FAILED],
+ 0);
+}
+
static gboolean
send_dbus_string_method (DBusConnection *connection,
const char *method,
@@ -645,6 +657,8 @@ client_dbus_handle_message (DBusConnection *connection,
on_ready (client, message);
} else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Reset")) {
on_reset (client, message);
+ } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "AuthenticationFailed")) {
+ on_authentication_failed (client, message);
} else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "SelectedUserChanged")) {
on_selected_user_changed (client, message);
} else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "DefaultLanguageNameChanged")) {
@@ -893,6 +907,16 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
+ gdm_greeter_client_signals[AUTHENTICATION_FAILED] =
+ g_signal_new ("authentication-failed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmGreeterClientClass, authentication_failed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
gdm_greeter_client_signals[SELECTED_USER_CHANGED] =
g_signal_new ("selected-user-changed",
G_OBJECT_CLASS_TYPE (object_class),
diff --git a/gui/simple-greeter/gdm-greeter-client.h b/gui/simple-greeter/gdm-greeter-client.h
index 08deabd..16ccef9 100644
--- a/gui/simple-greeter/gdm-greeter-client.h
+++ b/gui/simple-greeter/gdm-greeter-client.h
@@ -57,6 +57,7 @@ typedef struct
const char *problem);
void (* ready) (GdmGreeterClient *client);
void (* reset) (GdmGreeterClient *client);
+ void (* authentication_failed) (GdmGreeterClient *client);
void (* selected_user_changed) (GdmGreeterClient *client,
const char *username);
diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c
index f4794c8..fc9c7e3 100644
--- a/gui/simple-greeter/gdm-greeter-login-window.c
+++ b/gui/simple-greeter/gdm-greeter-login-window.c
@@ -546,34 +546,90 @@ switch_mode (GdmGreeterLoginWindow *login_window,
}
static void
-reset_dialog (GdmGreeterLoginWindow *login_window)
+choose_user (GdmGreeterLoginWindow *login_window,
+ const char *user_name)
+{
+ g_assert (user_name != NULL);
+
+ g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED],
+ 0, user_name);
+
+ if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) {
+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0);
+ } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) {
+ /* FIXME: handle guest account stuff */
+ } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) {
+ g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0,
+ login_window->priv->timed_login_username);
+
+ login_window->priv->timed_login_enabled = TRUE;
+ restart_timed_login_timeout (login_window);
+
+ /* just wait for the user to select language and stuff */
+ set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN);
+ set_message (login_window, _("Select language and click Log In"));
+ } else {
+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, user_name);
+ }
+
+ switch_mode (login_window, MODE_AUTHENTICATION);
+}
+
+static void
+retry_login (GdmGreeterLoginWindow *login_window)
+{
+ GtkWidget *entry;
+ char *user_name;
+
+ user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser));
+ if (user_name == NULL) {
+ return;
+ }
+
+ g_debug ("GdmGreeterLoginWindow: Retrying login for %s", user_name);
+
+ entry = GTK_WIDGET (gtk_builder_get_object (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->builder, "auth-prompt-entry"));
+ gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
+
+ choose_user (login_window, user_name);
+
+ g_free (user_name);
+}
+
+static void
+reset_dialog (GdmGreeterLoginWindow *login_window,
+ guint dialog_mode)
{
GtkWidget *entry;
GtkWidget *label;
- g_debug ("GdmGreeterLoginWindow: Resetting dialog");
+ g_debug ("GdmGreeterLoginWindow: Resetting dialog to mode %u", dialog_mode);
set_busy (login_window);
set_sensitive (login_window, FALSE);
- login_window->priv->show_cancel_button = FALSE;
+ if (dialog_mode == MODE_SELECTION) {
+ login_window->priv->show_cancel_button = FALSE;
- if (login_window->priv->timed_login_enabled) {
- gdm_chooser_widget_set_item_timer (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser),
- GDM_USER_CHOOSER_USER_AUTO, 0);
- remove_timed_login_timeout (login_window);
- login_window->priv->timed_login_enabled = FALSE;
- }
- _gdm_greeter_login_window_set_interactive (login_window, FALSE);
+ if (login_window->priv->timed_login_enabled) {
+ gdm_chooser_widget_set_item_timer (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser),
+ GDM_USER_CHOOSER_USER_AUTO, 0);
+ remove_timed_login_timeout (login_window);
+ login_window->priv->timed_login_enabled = FALSE;
+ }
+ _gdm_greeter_login_window_set_interactive (login_window, FALSE);
- g_signal_handlers_block_by_func (G_OBJECT (login_window->priv->user_chooser),
- G_CALLBACK (on_user_unchosen), login_window);
- gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), NULL);
- g_signal_handlers_unblock_by_func (G_OBJECT (login_window->priv->user_chooser),
- G_CALLBACK (on_user_unchosen), login_window);
+ g_signal_handlers_block_by_func (G_OBJECT (login_window->priv->user_chooser),
+ G_CALLBACK (on_user_unchosen), login_window);
+ gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), NULL);
+ g_signal_handlers_unblock_by_func (G_OBJECT (login_window->priv->user_chooser),
+ G_CALLBACK (on_user_unchosen), login_window);
- if (login_window->priv->start_session_handler_id > 0) {
- g_signal_handler_disconnect (login_window, login_window->priv->start_session_handler_id);
- login_window->priv->start_session_handler_id = 0;
+ if (login_window->priv->start_session_handler_id > 0) {
+ g_signal_handler_disconnect (login_window, login_window->priv->start_session_handler_id);
+ login_window->priv->start_session_handler_id = 0;
+ }
+
+ set_message (login_window, "");
}
entry = GTK_WIDGET (gtk_builder_get_object (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->builder, "auth-prompt-entry"));
@@ -581,7 +637,6 @@ reset_dialog (GdmGreeterLoginWindow *login_window)
gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE);
- set_message (login_window, "");
label = GTK_WIDGET (gtk_builder_get_object (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->builder, "auth-prompt-label"));
gtk_label_set_text (GTK_LABEL (label), "");
@@ -589,7 +644,7 @@ reset_dialog (GdmGreeterLoginWindow *login_window)
if (login_window->priv->user_list_disabled) {
switch_mode (login_window, MODE_AUTHENTICATION);
} else {
- switch_mode (login_window, MODE_SELECTION);
+ switch_mode (login_window, dialog_mode);
}
set_sensitive (login_window, TRUE);
@@ -597,6 +652,7 @@ reset_dialog (GdmGreeterLoginWindow *login_window)
set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
update_banner_message (login_window);
adjust_other_login_visibility (login_window);
+
if (gdm_chooser_widget_get_number_of_items (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)) >= 1) {
gdm_chooser_widget_propagate_pending_key_events (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser));
}
@@ -617,29 +673,46 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window)
{
g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
- reset_dialog (login_window);
-
set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE);
set_ready (GDM_GREETER_LOGIN_WINDOW (login_window));
set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
- /* If the user list is disabled, then start the PAM conversation */
- if (login_window->priv->user_list_disabled) {
- g_debug ("Starting PAM conversation since user list disabled");
- g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED],
- 0, GDM_USER_CHOOSER_USER_OTHER);
- g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0);
+ /* If we are retrying a previously selected user */
+ if (login_window->priv->dialog_mode != MODE_SELECTION) {
+ retry_login (login_window);
+ } else {
+ /* If the user list is disabled, then start the PAM conversation */
+ if (login_window->priv->user_list_disabled) {
+ g_debug ("Starting PAM conversation since user list disabled");
+ g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED],
+ 0, GDM_USER_CHOOSER_USER_OTHER);
+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0);
+ }
}
return TRUE;
}
gboolean
+gdm_greeter_login_window_authentication_failed (GdmGreeterLoginWindow *login_window)
+{
+ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
+
+ g_debug ("GdmGreeterLoginWindow: got authentication failed");
+
+ /* FIXME: shake? */
+ reset_dialog (login_window, MODE_AUTHENTICATION);
+
+ return TRUE;
+}
+
+gboolean
gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window)
{
g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
- reset_dialog (GDM_GREETER_LOGIN_WINDOW (login_window));
+ g_debug ("GdmGreeterLoginWindow: got reset");
+ reset_dialog (login_window, MODE_SELECTION);
return TRUE;
}
@@ -675,7 +748,7 @@ static void
handle_request_timed_login (GdmGreeterLoginWindow *login_window)
{
if (login_window->priv->dialog_mode != MODE_SELECTION) {
- reset_dialog (login_window);
+ reset_dialog (login_window, MODE_SELECTION);
}
gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), TRUE);
@@ -939,28 +1012,7 @@ on_user_chosen (GdmUserChooserWidget *user_chooser,
return;
}
- g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED],
- 0, user_name);
-
- if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) {
- g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0);
- } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) {
- /* FIXME: handle guest account stuff */
- } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) {
- g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0,
- login_window->priv->timed_login_username);
-
- login_window->priv->timed_login_enabled = TRUE;
- restart_timed_login_timeout (login_window);
-
- /* just wait for the user to select language and stuff */
- set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN);
- set_message (login_window, _("Select language and click Log In"));
- } else {
- g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, user_name);
- }
-
- switch_mode (login_window, MODE_AUTHENTICATION);
+ choose_user (login_window, user_name);
g_free (user_name);
}
diff --git a/gui/simple-greeter/gdm-greeter-login-window.h b/gui/simple-greeter/gdm-greeter-login-window.h
index 817d0a2..504b075 100644
--- a/gui/simple-greeter/gdm-greeter-login-window.h
+++ b/gui/simple-greeter/gdm-greeter-login-window.h
@@ -66,6 +66,7 @@ GtkWidget * gdm_greeter_login_window_new (gboolean displa
gboolean gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window);
+gboolean gdm_greeter_login_window_authentication_failed (GdmGreeterLoginWindow *login_window);
gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window);
gboolean gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window,
const char *text);
diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c
index 41336c6..7e5da1d 100644
--- a/gui/simple-greeter/gdm-greeter-session.c
+++ b/gui/simple-greeter/gdm-greeter-session.c
@@ -43,12 +43,16 @@
#define GDM_GREETER_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_SESSION, GdmGreeterSessionPrivate))
+#define MAX_LOGIN_TRIES 3
+
struct GdmGreeterSessionPrivate
{
GdmGreeterClient *client;
GtkWidget *login_window;
GtkWidget *panel;
+
+ guint num_tries;
};
enum {
@@ -98,11 +102,36 @@ on_reset (GdmGreeterClient *client,
{
g_debug ("GdmGreeterSession: Reset");
+ session->priv->num_tries = 0;
+
gdm_greeter_panel_reset (GDM_GREETER_PANEL (session->priv->panel));
gdm_greeter_login_window_reset (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window));
}
static void
+on_authentication_failed (GdmGreeterClient *client,
+ GdmGreeterSession *session)
+{
+ g_debug ("GdmGreeterSession: Authentication failed");
+
+ session->priv->num_tries++;
+
+ if (session->priv->num_tries < MAX_LOGIN_TRIES) {
+ g_debug ("GdmGreeterSession: Retrying login (%d)",
+ session->priv->num_tries);
+
+ gdm_greeter_login_window_authentication_failed (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window));
+ } else {
+ g_debug ("GdmGreeterSession: Maximum number of login tries exceeded (%d) - resetting",
+ session->priv->num_tries - 1);
+ session->priv->num_tries = 0;
+
+ gdm_greeter_panel_reset (GDM_GREETER_PANEL (session->priv->panel));
+ gdm_greeter_login_window_reset (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window));
+ }
+}
+
+static void
show_or_hide_user_options (GdmGreeterSession *session,
const char *username)
{
@@ -569,6 +598,10 @@ gdm_greeter_session_init (GdmGreeterSession *session)
G_CALLBACK (on_reset),
session);
g_signal_connect (session->priv->client,
+ "authentication-failed",
+ G_CALLBACK (on_authentication_failed),
+ session);
+ g_signal_connect (session->priv->client,
"selected-user-changed",
G_CALLBACK (on_selected_user_changed),
session);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]