Commit 0d928919 authored by Ray Strode's avatar Ray Strode

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".
parent a4f5409c
......@@ -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;
}
......
......@@ -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);
......
......@@ -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")) {
......
......@@ -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,
......
......@@ -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,
" <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"
......
......@@ -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;
}
......
......@@ -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)
......
......@@ -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,
......
......@@ -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);
......
......@@ -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),
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment