From 0d92891917576227b40eca56c4b173b879aa8792 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 28 Oct 2009 21:32:00 -0400 Subject: daemon: Distinguish "pam module failed" from "authentication failed" If pam_start() fails, that suggests the configured service stack is failing independent of the user account. This commit exposes that failure as "service unavailable" instead of "authentication failed". --- daemon/gdm-greeter-server.c | 13 ++++++++++-- daemon/gdm-greeter-server.h | 5 ++++- daemon/gdm-session-direct.c | 26 +++++++++++++++++++++--- daemon/gdm-session-private.h | 2 ++ daemon/gdm-session-relay.c | 33 ++++++++++++++++++++++++++++++ daemon/gdm-session-worker.c | 29 +++++++++++++++++++------- daemon/gdm-session.c | 21 +++++++++++++++++++ daemon/gdm-session.h | 2 ++ daemon/gdm-simple-slave.c | 36 +++++++++++++-------------------- gui/simple-greeter/gdm-greeter-client.c | 20 ++++++++++++++++++ gui/simple-greeter/gdm-greeter-client.h | 2 ++ 11 files changed, 154 insertions(+), 35 deletions(-) diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c index c7501dbb..e1475a4c 100644 --- a/daemon/gdm-greeter-server.c +++ b/daemon/gdm-greeter-server.c @@ -285,9 +285,18 @@ gdm_greeter_server_problem (GdmGreeterServer *greeter_server, } gboolean -gdm_greeter_server_authentication_failed (GdmGreeterServer *greeter_server) +gdm_greeter_server_authentication_failed (GdmGreeterServer *greeter_server, + const char *service_name) { - send_dbus_void_signal (greeter_server, "AuthenticationFailed"); + send_dbus_string_signal (greeter_server, "AuthenticationFailed", service_name); + return TRUE; +} + +gboolean +gdm_greeter_server_service_unavailable (GdmGreeterServer *greeter_server, + const char *service_name) +{ + send_dbus_string_signal (greeter_server, "ServiceUnavailable", service_name); return TRUE; } diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h index faa68961..c4c66a12 100644 --- a/daemon/gdm-greeter-server.h +++ b/daemon/gdm-greeter-server.h @@ -91,7 +91,10 @@ gboolean gdm_greeter_server_info (GdmGreeterServer * gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server, const char *service_name, const char *text); -gboolean gdm_greeter_server_authentication_failed (GdmGreeterServer *greeter_server); +gboolean gdm_greeter_server_authentication_failed (GdmGreeterServer *greeter_server, + const char *service_name); +gboolean gdm_greeter_server_service_unavailable (GdmGreeterServer *greeter_server, + const char *service_name); gboolean gdm_greeter_server_reset (GdmGreeterServer *greeter_server); gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server, const char *service_name); diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c index 8c2b0b2d..fa8ae49d 100644 --- a/daemon/gdm-session-direct.c +++ b/daemon/gdm-session-direct.c @@ -281,9 +281,27 @@ on_session_exited (GdmSession *session, } static DBusHandlerResult -gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, - GdmSessionConversation *conversation, - DBusMessage *message) +gdm_session_direct_handle_service_unavailable (GdmSessionDirect *session, + GdmSessionConversation *conversation, + DBusMessage *message) +{ + DBusMessage *reply; + + g_debug ("GdmSessionDirect: Emitting 'service-unavailable' signal"); + + reply = dbus_message_new_method_return (message); + dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + + _gdm_session_service_unavailable (GDM_SESSION (session), conversation->service_name); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, + GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; @@ -1237,6 +1255,8 @@ session_worker_message (DBusConnection *connection, return gdm_session_direct_handle_problem (session, conversation, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) { return gdm_session_direct_handle_cancel_pending_query (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ServiceUnavailable")) { + return gdm_session_direct_handle_service_unavailable (session, conversation, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) { return gdm_session_direct_handle_setup_complete (session, conversation, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) { diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h index e15b7dda..fb1f972e 100644 --- a/daemon/gdm-session-private.h +++ b/daemon/gdm-session-private.h @@ -31,6 +31,8 @@ void _gdm_session_conversation_started (GdmSession *sessio const char *service_name); void _gdm_session_conversation_stopped (GdmSession *session, const char *service_name); +void _gdm_session_service_unavailable (GdmSession *session, + const char *service_name); void _gdm_session_setup_complete (GdmSession *session, const char *service_name); void _gdm_session_setup_failed (GdmSession *session, diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c index 50f1140e..f76fa6fc 100644 --- a/daemon/gdm-session-relay.c +++ b/daemon/gdm-session-relay.c @@ -454,6 +454,34 @@ handle_problem (GdmSessionRelay *session_relay, return DBUS_HANDLER_RESULT_HANDLED; } +static DBusHandlerResult +handle_service_unavailable (GdmSessionRelay *session_relay, + DBusConnection *connection, + DBusMessage *message) +{ + DBusMessage *reply; + DBusError error; + char *service_name; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); + } + dbus_error_free (&error); + + g_debug ("GdmSessionRelay: ServiceUnavailable"); + + reply = dbus_message_new_method_return (message); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + + _gdm_session_service_unavailable (GDM_SESSION (session_relay), service_name); + + return DBUS_HANDLER_RESULT_HANDLED; +} + static DBusHandlerResult handle_setup_complete (GdmSessionRelay *session_relay, DBusConnection *connection, @@ -833,6 +861,8 @@ session_handle_child_message (DBusConnection *connection, return handle_info (session_relay, connection, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Problem")) { return handle_problem (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "ServiceUnavailable")) { + return handle_service_unavailable (session_relay, connection, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SetupComplete")) { return handle_setup_complete (session_relay, connection, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SetupFailed")) { @@ -890,6 +920,9 @@ do_introspect (DBusConnection *connection, " \n" " \n" " \n" + " \n" + " \n" + " \n" " \n" " \n" " \n" diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c index 2a891c1d..a7e2bd96 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -2004,9 +2004,16 @@ do_setup (GdmSessionWorker *worker) worker->priv->display_device, &error); if (! res) { - send_dbus_string_method (worker->priv->connection, - "SetupFailed", - error->message); + if (g_error_matches (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE)) { + send_dbus_void_method (worker->priv->connection, + "ServiceUnavailable"); + } else { + send_dbus_string_method (worker->priv->connection, + "SetupFailed", + error->message); + } g_error_free (error); return; } @@ -2027,10 +2034,18 @@ do_authenticate (GdmSessionWorker *worker) worker->priv->password_is_required, &error); if (! res) { - g_debug ("GdmSessionWorker: Unable to verify user"); - send_dbus_string_method (worker->priv->connection, - "AuthenticationFailed", - error->message); + if (g_error_matches (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE)) { + g_debug ("GdmSessionWorker: Unable to use authentication service"); + send_dbus_void_method (worker->priv->connection, + "ServiceUnavailable"); + } else { + g_debug ("GdmSessionWorker: Unable to verify user"); + send_dbus_string_method (worker->priv->connection, + "AuthenticationFailed", + error->message); + } g_error_free (error); return; } diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index 4c7f6bc2..bf7c878e 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -31,6 +31,7 @@ enum { CONVERSATION_STARTED = 0, CONVERSATION_STOPPED, + SERVICE_UNAVAILABLE, SETUP_COMPLETE, SETUP_FAILED, RESET_COMPLETE, @@ -241,6 +242,17 @@ gdm_session_class_init (gpointer g_iface) g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + signals [SERVICE_UNAVAILABLE] = + g_signal_new ("service-unavailable", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionIface, service_unavailable), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); signals [SETUP_COMPLETE] = g_signal_new ("setup-complete", iface_type, @@ -503,6 +515,15 @@ gdm_session_class_init (gpointer g_iface) G_TYPE_STRING); } +void +_gdm_session_service_unavailable (GdmSession *session, + const char *service_name) +{ + g_return_if_fail (GDM_IS_SESSION (session)); + + g_signal_emit (session, signals [SERVICE_UNAVAILABLE], 0, service_name); +} + void _gdm_session_setup_complete (GdmSession *session, const char *service_name) diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h index 9e72f898..ab160318 100644 --- a/daemon/gdm-session.h +++ b/daemon/gdm-session.h @@ -49,6 +49,8 @@ struct _GdmSessionIface const char *service_name); void (* stop_conversation) (GdmSession *session, const char *service_name); + void (* service_unavailable) (GdmSession *session, + const char *service_name); void (* setup) (GdmSession *session, const char *service_name); void (* setup_for_user) (GdmSession *session, diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 6eb1448e..7b9d7d8b 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -266,22 +266,6 @@ 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) { @@ -293,14 +277,16 @@ queue_greeter_reset (GdmSimpleSlave *slave) } static void -queue_auth_failed_reset (GdmSimpleSlave *slave) +on_session_service_unavailable (GdmSession *session, + const char *service_name, + GdmSimpleSlave *slave) { - /* use the greeter reset idle id so we don't do both at once */ - if (slave->priv->greeter_reset_id > 0) { - return; + if (slave->priv->greeter_server != NULL) { + gdm_greeter_server_service_unavailable (slave->priv->greeter_server, + service_name); } - slave->priv->greeter_reset_id = g_idle_add ((GSourceFunc)auth_failed_reset_timeout, slave); + gdm_session_stop_conversation (session, service_name); } static void @@ -363,7 +349,6 @@ on_session_authentication_failed (GdmSession *session, g_debug ("GdmSimpleSlave: Authentication failed - may retry"); gdm_session_stop_conversation (session, service_name); - queue_auth_failed_reset (slave); } static void @@ -787,6 +772,10 @@ create_new_session (GdmSimpleSlave *slave) "conversation-stopped", G_CALLBACK (on_session_conversation_stopped), slave); + g_signal_connect (slave->priv->session, + "service-unavailable", + G_CALLBACK (on_session_service_unavailable), + slave); g_signal_connect (slave->priv->session, "setup-complete", G_CALLBACK (on_session_setup_complete), @@ -900,6 +889,9 @@ destroy_session (GdmSimpleSlave *slave) g_signal_handlers_disconnect_by_func (slave->priv->session, G_CALLBACK (on_session_conversation_stopped), slave); + g_signal_handlers_disconnect_by_func (slave->priv->session, + G_CALLBACK (on_session_service_unavailable), + slave); g_signal_handlers_disconnect_by_func (slave->priv->session, G_CALLBACK (on_session_setup_complete), slave); diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c index e9916266..65d21d91 100644 --- a/gui/simple-greeter/gdm-greeter-client.c +++ b/gui/simple-greeter/gdm-greeter-client.c @@ -63,6 +63,7 @@ enum { PROBLEM, INFO_QUERY, SECRET_INFO_QUERY, + SERVICE_UNAVAILABLE, READY, RESET, AUTHENTICATION_FAILED, @@ -255,6 +256,13 @@ on_problem (GdmGreeterClient *client, emit_string_and_string_signal_for_message (client, "Problem", message, PROBLEM); } +static void +on_service_unavailable (GdmGreeterClient *client, + DBusMessage *message) +{ + emit_string_signal_for_message (client, "ServiceUnavailable", message, SERVICE_UNAVAILABLE); +} + static void on_ready (GdmGreeterClient *client, DBusMessage *message) @@ -730,6 +738,8 @@ client_dbus_handle_message (DBusConnection *connection, on_info (client, message); } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Problem")) { on_problem (client, message); + } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "ServiceUnavailable")) { + on_service_unavailable (client, message); } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Ready")) { on_ready (client, message); } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Reset")) { @@ -961,6 +971,16 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) 2, G_TYPE_STRING, G_TYPE_STRING); + gdm_greeter_client_signals[SERVICE_UNAVAILABLE] = + g_signal_new ("service-unavailable", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmGreeterClientClass, service_unavailable), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + gdm_greeter_client_signals[READY] = g_signal_new ("ready", 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 658da484..124f53d0 100644 --- a/gui/simple-greeter/gdm-greeter-client.h +++ b/gui/simple-greeter/gdm-greeter-client.h @@ -59,6 +59,8 @@ typedef struct void (* problem) (GdmGreeterClient *client, const char *service_name, const char *problem); + void (* service_unavailable) (GdmGreeterClient *client, + const char *service_name); void (* ready) (GdmGreeterClient *client, const char *service_name); void (* reset) (GdmGreeterClient *client); -- cgit v1.2.1