[gdm/remotes/origin/wip/multi-stack: 5/9] daemon: Distinguish "pam module failed" from "authentication failed"



commit d4b47ac36507f8e40fcfe483f94bfa563328ce1b
Author: Ray Strode <rstrode redhat com>
Date:   Wed Oct 28 21:32:00 2009 -0400

    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 c7501db..e1475a4 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 faa6896..c4c66a1 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 8c2b0b2..fa8ae49 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 e15b7dd..fb1f972 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 50f1140..f76fa6f 100644
--- a/daemon/gdm-session-relay.c
+++ b/daemon/gdm-session-relay.c
@@ -455,6 +455,34 @@ handle_problem (GdmSessionRelay *session_relay,
 }
 
 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,
                        DBusMessage     *message)
@@ -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,
                                "    <method name=\"ConversationStarted\">\n"
                                "      <arg name=\"service_name\" direction=\"in\" type=\"s\"/>\n"
                                "    </method>\n"
+                               "    <method name=\"ServiceUnavailable\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
                                "    <method name=\"SetupComplete\">\n"
                                "    </method>\n"
                                "    <method name=\"SetupFailed\">\n"
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index a6f40c7..ce2de45 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 4c7f6bc..bf7c878 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,
@@ -504,6 +516,15 @@ gdm_session_class_init (gpointer g_iface)
 }
 
 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 9e72f89..ab16031 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 6eb1448..7b9d7d8 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
@@ -788,6 +773,10 @@ create_new_session (GdmSimpleSlave *slave)
                           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),
                           slave);
@@ -901,6 +890,9 @@ destroy_session (GdmSimpleSlave *slave)
                                               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);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c
index e991626..65d21d9 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,
@@ -256,6 +257,13 @@ on_problem (GdmGreeterClient *client,
 }
 
 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 658da48..124f53d 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);



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