2 * Copyright (C) 2010 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
5 * This library is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License as published by the Free
7 * Software Foundation; either version 2 or version 3 of the License.
8 * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
16 #include <gio/gunixsocketaddress.h>
17 #include <security/pam_appl.h>
19 #include "lightdm/greeter.h"
21 G_DEFINE_QUARK (lightdm_greeter_error, lightdm_greeter_error)
25 PROP_DEFAULT_SESSION_HINT,
27 PROP_SHOW_MANUAL_LOGIN_HINT,
28 PROP_SHOW_REMOTE_LOGIN_HINT,
30 PROP_HAS_GUEST_ACCOUNT_HINT,
31 PROP_SELECT_USER_HINT,
32 PROP_SELECT_GUEST_HINT,
33 PROP_AUTOLOGIN_USER_HINT,
34 PROP_AUTOLOGIN_GUEST_HINT,
35 PROP_AUTOLOGIN_TIMEOUT_HINT,
36 PROP_AUTHENTICATION_USER,
37 PROP_IN_AUTHENTICATION,
38 PROP_IS_AUTHENTICATED,
44 AUTHENTICATION_COMPLETE,
45 AUTOLOGIN_TIMER_EXPIRED,
50 static guint signals[LAST_SIGNAL] = { 0 };
54 /* TRUE if the daemon can reuse this greeter */
57 /* Socket connection to daemon */
60 /* Channel to write to daemon */
61 GIOChannel *to_server_channel;
63 /* Channel to read from daemon */
64 GIOChannel *from_server_channel;
66 /* Data read from the daemon */
70 gsize n_responses_waiting;
71 GList *responses_received;
73 /* TRUE if have got a connect response */
76 /* Pending connect requests */
77 GList *connect_requests;
79 /* Pending start session requests */
80 GList *start_session_requests;
82 /* Pending ensure shared data dir requests */
83 GList *ensure_shared_data_dir_requests;
85 /* Hints provided by the daemon */
88 /* Timeout source to notify greeter to autologin */
89 guint autologin_timeout;
91 gchar *authentication_user;
92 gboolean in_authentication;
93 gboolean is_authenticated;
94 guint32 authenticate_sequence_number;
95 gboolean cancelling_authentication;
96 } LightDMGreeterPrivate;
98 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
100 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
102 #define HEADER_SIZE 8
103 #define MAX_MESSAGE_LENGTH 1024
105 /* Messages from the greeter to the server */
108 GREETER_MESSAGE_CONNECT = 0,
109 GREETER_MESSAGE_AUTHENTICATE,
110 GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
111 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
112 GREETER_MESSAGE_START_SESSION,
113 GREETER_MESSAGE_CANCEL_AUTHENTICATION,
114 GREETER_MESSAGE_SET_LANGUAGE,
115 GREETER_MESSAGE_AUTHENTICATE_REMOTE,
116 GREETER_MESSAGE_ENSURE_SHARED_DIR,
119 /* Messages from the server to the greeter */
122 SERVER_MESSAGE_CONNECTED = 0,
123 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
124 SERVER_MESSAGE_END_AUTHENTICATION,
125 SERVER_MESSAGE_SESSION_RESULT,
126 SERVER_MESSAGE_SHARED_DIR_RESULT,
128 SERVER_MESSAGE_RESET,
131 /* Request sent to server */
134 GObject parent_instance;
135 LightDMGreeter *greeter;
136 GCancellable *cancellable;
137 GAsyncReadyCallback callback;
146 GObjectClass parent_class;
148 GType request_get_type (void);
149 static void request_iface_init (GAsyncResultIface *iface);
150 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
151 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
153 static gboolean from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data);
156 lightdm_greeter_error_get_type (void)
158 static GType enum_type = 0;
160 if (G_UNLIKELY(enum_type == 0)) {
161 static const GEnumValue values[] = {
162 { LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR, "LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR", "communication-error" },
163 { LIGHTDM_GREETER_ERROR_CONNECTION_FAILED, "LIGHTDM_GREETER_ERROR_CONNECTION_FAILED", "connection-failed" },
164 { LIGHTDM_GREETER_ERROR_SESSION_FAILED, "LIGHTDM_GREETER_ERROR_SESSION_FAILED", "session-failed" },
165 { LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN, "LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN", "no-autologin" },
166 { LIGHTDM_GREETER_ERROR_INVALID_USER, "LIGHTDM_GREETER_ERROR_INVALID_USER", "invalid-user" },
169 enum_type = g_enum_register_static (g_intern_static_string ("LightDMGreeterError"), values);
176 lightdm_prompt_type_get_type (void)
178 static GType enum_type = 0;
180 if (G_UNLIKELY(enum_type == 0)) {
181 static const GEnumValue values[] = {
182 { LIGHTDM_PROMPT_TYPE_QUESTION, "LIGHTDM_PROMPT_TYPE_QUESTION", "question" },
183 { LIGHTDM_PROMPT_TYPE_SECRET, "LIGHTDM_PROMPT_TYPE_SECRET", "secret" },
186 enum_type = g_enum_register_static (g_intern_static_string ("LightDMPromptType"), values);
193 lightdm_message_type_get_type (void)
195 static GType enum_type = 0;
197 if (G_UNLIKELY(enum_type == 0)) {
198 static const GEnumValue values[] = {
199 { LIGHTDM_MESSAGE_TYPE_INFO, "LIGHTDM_MESSAGE_TYPE_INFO", "info" },
200 { LIGHTDM_MESSAGE_TYPE_ERROR, "LIGHTDM_MESSAGE_TYPE_ERROR", "error" },
203 enum_type = g_enum_register_static (g_intern_static_string ("LightDMMessageType"), values);
211 * lightdm_greeter_new:
213 * Create a new greeter.
215 * Return value: the new #LightDMGreeter
218 lightdm_greeter_new (void)
220 return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
224 * lightdm_greeter_set_resettable:
225 * @greeter: A #LightDMGreeter
226 * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
228 * Set whether the greeter will be reset instead of killed after the user logs in.
229 * This must be called before lightdm_greeter_connect is called.
232 lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
234 LightDMGreeterPrivate *priv;
236 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
238 priv = GET_PRIVATE (greeter);
240 g_return_if_fail (!priv->connected);
241 priv->resettable = resettable;
245 request_new (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
249 request = g_object_new (request_get_type (), NULL);
250 request->greeter = g_object_ref (greeter);
252 request->cancellable = g_object_ref (cancellable);
253 request->callback = callback;
254 request->user_data = user_data;
260 request_callback_cb (gpointer data)
262 Request *request = data;
263 if (request->callback)
264 request->callback (G_OBJECT (request->greeter), G_ASYNC_RESULT (request), request->user_data);
265 g_object_unref (request);
266 return G_SOURCE_REMOVE;
270 request_complete (Request *request)
272 request->complete = TRUE;
274 if (!request->callback)
277 if (request->cancellable && g_cancellable_is_cancelled (request->cancellable))
280 g_idle_add (request_callback_cb, g_object_ref (request));
284 timed_login_cb (gpointer data)
286 LightDMGreeter *greeter = data;
287 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
289 priv->autologin_timeout = 0;
290 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
302 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset, GError **error)
304 if (*offset + 4 >= buffer_length)
306 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
307 "Not enough buffer space to write integer");
310 buffer[*offset] = value >> 24;
311 buffer[*offset+1] = (value >> 16) & 0xFF;
312 buffer[*offset+2] = (value >> 8) & 0xFF;
313 buffer[*offset+3] = value & 0xFF;
320 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset, GError **error)
325 length = strlen (value);
326 if (!write_int (buffer, buffer_length, length, offset, error))
328 if (*offset + length >= buffer_length)
330 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
331 "Not enough buffer space to write string of length %d octets", length);
335 memcpy (buffer + *offset, value, length);
342 read_int (guint8 *message, gsize message_length, gsize *offset)
347 if (message_length - *offset < int_length ())
349 g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
353 buffer = message + *offset;
354 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
355 *offset += int_length ();
361 read_string (guint8 *message, gsize message_length, gsize *offset)
366 length = read_int (message, message_length, offset);
367 if (message_length - *offset < length)
369 g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
370 return g_strdup ("");
373 value = g_malloc (sizeof (gchar) * (length + 1));
374 memcpy (value, message + *offset, length);
375 value[length] = '\0';
382 string_length (const gchar *value)
385 return int_length () + strlen (value);
387 return int_length ();
391 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset, GError **error)
393 return write_int (buffer, buffer_length, id, offset, error) &&
394 write_int (buffer, buffer_length, length, offset, error);
398 get_message_length (guint8 *message, gsize message_length)
401 return read_int (message, message_length, &offset);
405 connect_to_daemon (LightDMGreeter *greeter, GError **error)
407 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
408 const gchar *to_server_fd, *from_server_fd, *pipe_path;
410 if (priv->to_server_channel || priv->from_server_channel)
413 /* Use private connection if one exists */
414 to_server_fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
415 from_server_fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
416 pipe_path = g_getenv ("LIGHTDM_GREETER_PIPE");
417 if (to_server_fd && from_server_fd)
419 priv->to_server_channel = g_io_channel_unix_new (atoi (to_server_fd));
420 priv->from_server_channel = g_io_channel_unix_new (atoi (from_server_fd));
424 GSocketAddress *address;
427 priv->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error);
431 address = g_unix_socket_address_new (pipe_path);
432 result = g_socket_connect (priv->socket, address, NULL, error);
433 g_object_unref (address);
437 priv->from_server_channel = g_io_channel_unix_new (g_socket_get_fd (priv->socket));
438 priv->to_server_channel = g_io_channel_ref (priv->from_server_channel);
442 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_CONNECTION_FAILED,
443 "Unable to determine socket to daemon");
447 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
449 if (!g_io_channel_set_encoding (priv->to_server_channel, NULL, error) ||
450 !g_io_channel_set_encoding (priv->from_server_channel, NULL, error))
457 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length, GError **error)
459 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
462 guint32 stated_length;
463 GError *flush_error = NULL;
465 if (!connect_to_daemon (greeter, error))
468 /* Double check that we're sending well-formed messages. If we say we're
469 sending more than we do, we end up DOS'ing lightdm as it waits for the
470 rest. If we say we're sending less than we do, we confuse the heck out
471 of lightdm, as it starts reading headers from the middle of our
473 stated_length = HEADER_SIZE + get_message_length (message, message_length);
474 if (stated_length != message_length)
476 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
477 "Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu",
478 stated_length, message_length);
482 data = (gchar *) message;
483 data_length = message_length;
484 while (data_length > 0)
488 GError *write_error = NULL;
490 status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &write_error);
492 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
493 "Failed to write to daemon: %s",
494 write_error->message);
495 g_clear_error (&write_error);
496 if (status == G_IO_STATUS_AGAIN)
498 if (status != G_IO_STATUS_NORMAL)
500 data_length -= n_written;
504 g_debug ("Wrote %zi bytes to daemon", message_length);
505 if (!g_io_channel_flush (priv->to_server_channel, &flush_error))
507 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
508 "Failed to write to daemon: %s",
509 flush_error->message);
510 g_clear_error (&flush_error);
518 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
520 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
522 GString *hint_string;
526 version = read_string (message, message_length, offset);
527 hint_string = g_string_new ("");
528 while (*offset < message_length)
532 name = read_string (message, message_length, offset);
533 value = read_string (message, message_length, offset);
534 g_hash_table_insert (priv->hints, name, value);
535 g_string_append_printf (hint_string, " %s=%s", name, value);
538 priv->connected = TRUE;
539 g_debug ("Connected version=%s%s", version, hint_string->str);
541 g_string_free (hint_string, TRUE);
543 /* Set timeout for default login */
544 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
547 g_debug ("Setting autologin timer for %d seconds", timeout);
548 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
551 /* Notify asynchronous caller */
552 request = g_list_nth_data (priv->connect_requests, 0);
555 request->result = TRUE;
556 request_complete (request);
557 priv->connect_requests = g_list_remove (priv->connect_requests, request);
558 g_object_unref (request);
563 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
565 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
566 guint32 sequence_number, n_messages, i;
569 sequence_number = read_int (message, message_length, offset);
570 if (sequence_number != priv->authenticate_sequence_number)
572 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
576 if (priv->cancelling_authentication)
578 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
582 /* Update username */
583 username = read_string (message, message_length, offset);
584 if (strcmp (username, "") == 0)
589 g_free (priv->authentication_user);
590 priv->authentication_user = username;
592 g_list_free_full (priv->responses_received, g_free);
593 priv->responses_received = NULL;
594 priv->n_responses_waiting = 0;
596 n_messages = read_int (message, message_length, offset);
597 g_debug ("Prompt user with %d message(s)", n_messages);
599 for (i = 0; i < n_messages; i++)
604 style = read_int (message, message_length, offset);
605 text = read_string (message, message_length, offset);
607 // FIXME: Should stop on prompts?
610 case PAM_PROMPT_ECHO_OFF:
611 priv->n_responses_waiting++;
612 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
614 case PAM_PROMPT_ECHO_ON:
615 priv->n_responses_waiting++;
616 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
619 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
622 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
631 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
633 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
634 guint32 sequence_number, return_code;
637 sequence_number = read_int (message, message_length, offset);
639 if (sequence_number != priv->authenticate_sequence_number)
641 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
645 username = read_string (message, message_length, offset);
646 return_code = read_int (message, message_length, offset);
648 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
650 /* Update username */
651 if (strcmp (username, "") == 0)
656 g_free (priv->authentication_user);
657 priv->authentication_user = username;
659 priv->cancelling_authentication = FALSE;
660 priv->is_authenticated = (return_code == 0);
662 priv->in_authentication = FALSE;
663 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
667 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
669 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
673 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
675 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
676 GString *hint_string;
678 g_hash_table_remove_all (priv->hints);
680 hint_string = g_string_new ("");
681 while (*offset < message_length)
685 name = read_string (message, message_length, offset);
686 value = read_string (message, message_length, offset);
687 g_hash_table_insert (priv->hints, name, value);
688 g_string_append_printf (hint_string, " %s=%s", name, value);
691 g_debug ("Reset%s", hint_string->str);
692 g_string_free (hint_string, TRUE);
694 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
698 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
700 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
703 /* Notify asynchronous caller */
704 request = g_list_nth_data (priv->start_session_requests, 0);
709 return_code = read_int (message, message_length, offset);
710 if (return_code == 0)
711 request->result = TRUE;
713 request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_SESSION_FAILED,
714 "Session returned error code %d", return_code);
715 request_complete (request);
716 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
717 g_object_unref (request);
722 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
724 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
727 /* Notify asynchronous caller */
728 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
731 request->dir = read_string (message, message_length, offset);
732 /* Blank data dir means invalid user */
733 if (g_strcmp0 (request->dir, "") == 0)
735 g_free (request->dir);
737 request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_INVALID_USER,
740 request_complete (request);
741 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
742 g_object_unref (request);
747 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
752 id = read_int (message, message_length, &offset);
753 read_int (message, message_length, &offset);
756 case SERVER_MESSAGE_CONNECTED:
757 handle_connected (greeter, message, message_length, &offset);
759 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
760 handle_prompt_authentication (greeter, message, message_length, &offset);
762 case SERVER_MESSAGE_END_AUTHENTICATION:
763 handle_end_authentication (greeter, message, message_length, &offset);
765 case SERVER_MESSAGE_SESSION_RESULT:
766 handle_session_result (greeter, message, message_length, &offset);
768 case SERVER_MESSAGE_SHARED_DIR_RESULT:
769 handle_shared_dir_result (greeter, message, message_length, &offset);
771 case SERVER_MESSAGE_IDLE:
772 handle_idle (greeter, message, message_length, &offset);
774 case SERVER_MESSAGE_RESET:
775 handle_reset (greeter, message, message_length, &offset);
778 g_warning ("Unknown message from server: %d", id);
784 recv_message (LightDMGreeter *greeter, gboolean block, guint8 **message, gsize *length, GError **error)
786 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
787 gsize n_to_read, n_read;
789 if (!connect_to_daemon (greeter, error))
792 /* Read the header, or the whole message if we already have that */
793 n_to_read = HEADER_SIZE;
794 if (priv->n_read >= HEADER_SIZE)
795 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
800 GError *read_error = NULL;
802 status = g_io_channel_read_chars (priv->from_server_channel,
803 (gchar *) priv->read_buffer + priv->n_read,
804 n_to_read - priv->n_read,
807 if (status == G_IO_STATUS_AGAIN)
812 else if (status != G_IO_STATUS_NORMAL)
814 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
815 "Failed to read from daemon: %s",
816 read_error->message);
817 g_clear_error (&read_error);
821 g_debug ("Read %zi bytes from daemon", n_read);
823 priv->n_read += n_read;
824 } while (priv->n_read < n_to_read && block);
826 /* Stop if haven't got all the data we want */
827 if (priv->n_read != n_to_read)
836 /* If have header, rerun for content */
837 if (priv->n_read == HEADER_SIZE)
839 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
842 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
843 return recv_message (greeter, block, message, length, error);
848 *message = priv->read_buffer;
850 g_free (priv->read_buffer);
852 *length = priv->n_read;
854 priv->read_buffer = g_malloc (priv->n_read);
861 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
863 LightDMGreeter *greeter = data;
865 gsize message_length;
866 GError *error = NULL;
868 /* Read one message and process it */
869 if (!recv_message (greeter, FALSE, &message, &message_length, &error))
871 // FIXME: Should push this up to the client somehow
872 g_warning ("Failed to read from daemon: %s\n", error->message);
873 g_clear_error (&error);
874 return G_SOURCE_REMOVE;
879 handle_message (greeter, message, message_length);
883 return G_SOURCE_CONTINUE;
887 send_connect (LightDMGreeter *greeter, gboolean resettable, GError **error)
889 guint8 message[MAX_MESSAGE_LENGTH];
892 g_debug ("Connecting to display manager...");
893 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset, error) &&
894 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset, error) &&
895 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset, error) &&
896 send_message (greeter, message, offset, error);
900 send_start_session (LightDMGreeter *greeter, const gchar *session, GError **error)
902 guint8 message[MAX_MESSAGE_LENGTH];
906 g_debug ("Starting session %s", session);
908 g_debug ("Starting default session");
910 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset, error) &&
911 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
912 send_message (greeter, message, offset, error);
916 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GError **error)
918 guint8 message[MAX_MESSAGE_LENGTH];
921 g_debug ("Ensuring data directory for user %s", username);
923 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset, error) &&
924 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
925 send_message (greeter, message, offset, error);
929 * lightdm_greeter_connect_to_daemon:
930 * @greeter: The greeter to connect
931 * @cancellable: (allow-none): A #GCancellable or %NULL.
932 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
933 * @user_data: (allow-none): data to pass to the @callback or %NULL.
935 * Asynchronously connects the greeter to the display manager.
937 * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_to_daemon_finish() to get the result of the operation.
939 * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
942 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
944 LightDMGreeterPrivate *priv;
946 GError *error = NULL;
948 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
950 priv = GET_PRIVATE (greeter);
952 request = request_new (greeter, cancellable, callback, user_data);
953 if (send_connect (greeter, priv->resettable, &error))
954 priv->connect_requests = g_list_append (priv->connect_requests, request);
957 request->error = error;
958 request_complete (request);
959 g_object_unref (request);
964 * lightdm_greeter_connect_to_daemon_finish:
965 * @greeter: The greeter the the request was done with
966 * @result: A #GAsyncResult.
967 * @error: return location for a #GError, or %NULL
969 * Finishes an operation started with lightdm_greeter_connect_to_daemon().
971 * Return value: #TRUE if successfully connected
974 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
976 Request *request = REQUEST (result);
978 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
981 g_propagate_error (error, request->error);
982 return request->result;
986 * lightdm_greeter_connect_to_daemon_sync:
987 * @greeter: The greeter to connect
988 * @error: return location for a #GError, or %NULL
990 * Connects the greeter to the display manager. Will block until connected.
992 * Return value: #TRUE if successfully connected
995 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
997 LightDMGreeterPrivate *priv;
1000 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1002 priv = GET_PRIVATE (greeter);
1004 /* Read until we are connected */
1005 if (!send_connect (greeter, priv->resettable, error))
1007 request = request_new (greeter, NULL, NULL, NULL);
1008 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
1012 gsize message_length;
1014 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1016 handle_message (greeter, message, message_length);
1018 } while (!request->complete);
1020 return lightdm_greeter_connect_to_daemon_finish (greeter, G_ASYNC_RESULT (request), error);
1024 * lightdm_greeter_connect_sync:
1025 * @greeter: The greeter to connect
1026 * @error: return location for a #GError, or %NULL
1028 * Connects the greeter to the display manager. Will block until connected.
1030 * Return value: #TRUE if successfully connected
1032 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
1035 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
1037 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
1041 * lightdm_greeter_get_hint:
1042 * @greeter: A #LightDMGreeter
1043 * @name: The hint name to query.
1047 * Return value: (nullable): The value for this hint or #NULL if not set.
1050 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
1052 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1053 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
1057 * lightdm_greeter_get_default_session_hint:
1058 * @greeter: A #LightDMGreeter
1060 * Get the default session to use.
1062 * Return value: The session name
1065 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
1067 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1068 return lightdm_greeter_get_hint (greeter, "default-session");
1072 * lightdm_greeter_get_hide_users_hint:
1073 * @greeter: A #LightDMGreeter
1075 * Check if user accounts should be shown. If this is TRUE then the list of
1076 * accounts should be taken from #LightDMUserList and displayed in the greeter
1077 * for the user to choose from. Note that this list can be empty and it is
1078 * recommended you show a method for the user to enter a username manually.
1080 * If this option is shown the greeter should only allow these users to be
1081 * chosen for login unless the manual login hint is set.
1083 * Return value: #TRUE if the available users should not be shown.
1086 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
1090 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1091 value = lightdm_greeter_get_hint (greeter, "hide-users");
1093 return g_strcmp0 (value, "true") == 0;
1097 * lightdm_greeter_get_show_manual_login_hint:
1098 * @greeter: A #LightDMGreeter
1100 * Check if a manual login option should be shown. If set the GUI
1101 * should provide a way for a username to be entered manually.
1102 * Without this hint a greeter which is showing a user list can
1103 * limit logins to only those users.
1105 * Return value: #TRUE if a manual login option should be shown.
1108 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
1112 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1113 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
1115 return g_strcmp0 (value, "true") == 0;
1119 * lightdm_greeter_get_show_remote_login_hint:
1120 * @greeter: A #LightDMGreeter
1122 * Check if a remote login option should be shown. If set the GUI
1123 * should provide a way for a user to log into a remote desktop server.
1125 * Return value: #TRUE if a remote login option should be shown.
1128 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
1132 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1133 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
1135 return g_strcmp0 (value, "true") == 0;
1139 * lightdm_greeter_get_lock_hint:
1140 * @greeter: A #LightDMGreeter
1142 * Check if the greeter is acting as a lock screen.
1144 * Return value: #TRUE if the greeter was triggered by locking the seat.
1147 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
1151 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1152 value = lightdm_greeter_get_hint (greeter, "lock-screen");
1154 return g_strcmp0 (value, "true") == 0;
1158 * lightdm_greeter_get_has_guest_account_hint:
1159 * @greeter: A #LightDMGreeter
1161 * Check if guest sessions are supported.
1163 * Return value: #TRUE if guest sessions are supported.
1166 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
1170 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1171 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
1173 return g_strcmp0 (value, "true") == 0;
1177 * lightdm_greeter_get_select_user_hint:
1178 * @greeter: A #LightDMGreeter
1180 * Get the user to select by default.
1182 * Return value: (nullable): A username or %NULL if no particular user should be selected.
1185 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
1187 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1188 return lightdm_greeter_get_hint (greeter, "select-user");
1192 * lightdm_greeter_get_select_guest_hint:
1193 * @greeter: A #LightDMGreeter
1195 * Check if the guest account should be selected by default.
1197 * Return value: #TRUE if the guest account should be selected by default.
1200 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1204 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1205 value = lightdm_greeter_get_hint (greeter, "select-guest");
1207 return g_strcmp0 (value, "true") == 0;
1211 * lightdm_greeter_get_autologin_user_hint:
1212 * @greeter: A #LightDMGreeter
1214 * Get the user account to automatically log into when the timer expires.
1216 * Return value: (nullable): The user account to automatically log into or %NULL if none configured.
1219 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1221 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1222 return lightdm_greeter_get_hint (greeter, "autologin-user");
1226 * lightdm_greeter_get_autologin_guest_hint:
1227 * @greeter: A #LightDMGreeter
1229 * Check if the guest account should be automatically logged into when the timer expires.
1231 * Return value: #TRUE if the guest account should be automatically logged into.
1234 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1238 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1239 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1241 return g_strcmp0 (value, "true") == 0;
1245 * lightdm_greeter_get_autologin_timeout_hint:
1246 * @greeter: A #LightDMGreeter
1248 * Get the number of seconds to wait before automaitcally logging in.
1250 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1253 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1258 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1259 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1261 timeout = atoi (value);
1269 * lightdm_greeter_cancel_autologin:
1270 * @greeter: A #LightDMGreeter
1272 * Cancel the automatic login.
1275 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1277 LightDMGreeterPrivate *priv;
1279 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1281 priv = GET_PRIVATE (greeter);
1283 if (priv->autologin_timeout)
1284 g_source_remove (priv->autologin_timeout);
1285 priv->autologin_timeout = 0;
1289 * lightdm_greeter_authenticate:
1290 * @greeter: A #LightDMGreeter
1291 * @username: (allow-none): A username or #NULL to prompt for a username.
1292 * @error: return location for a #GError, or %NULL
1294 * Starts the authentication procedure for a user.
1296 * Return value: #TRUE if authentication request sent.
1299 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username, GError **error)
1301 LightDMGreeterPrivate *priv;
1302 guint8 message[MAX_MESSAGE_LENGTH];
1305 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1307 priv = GET_PRIVATE (greeter);
1309 g_return_val_if_fail (priv->connected, FALSE);
1311 priv->cancelling_authentication = FALSE;
1312 priv->authenticate_sequence_number++;
1313 priv->in_authentication = TRUE;
1314 priv->is_authenticated = FALSE;
1315 if (username != priv->authentication_user)
1317 g_free (priv->authentication_user);
1318 priv->authentication_user = g_strdup (username);
1321 g_debug ("Starting authentication for user %s...", username);
1322 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset, error) &&
1323 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1324 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1325 send_message (greeter, message, offset, error);
1329 * lightdm_greeter_authenticate_as_guest:
1330 * @greeter: A #LightDMGreeter
1331 * @error: return location for a #GError, or %NULL
1333 * Starts the authentication procedure for the guest user.
1335 * Return value: #TRUE if authentication request sent.
1338 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter, GError **error)
1340 LightDMGreeterPrivate *priv;
1341 guint8 message[MAX_MESSAGE_LENGTH];
1344 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1346 priv = GET_PRIVATE (greeter);
1348 g_return_val_if_fail (priv->connected, FALSE);
1350 priv->cancelling_authentication = FALSE;
1351 priv->authenticate_sequence_number++;
1352 priv->in_authentication = TRUE;
1353 priv->is_authenticated = FALSE;
1354 g_free (priv->authentication_user);
1355 priv->authentication_user = NULL;
1357 g_debug ("Starting authentication for guest account...");
1358 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset, error) &&
1359 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1360 send_message (greeter, message, offset, error);
1364 * lightdm_greeter_authenticate_autologin:
1365 * @greeter: A #LightDMGreeter
1366 * @error: return location for a #GError, or %NULL
1368 * Starts the authentication procedure for the automatic login user.
1370 * Return value: #TRUE if authentication request sent.
1373 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter, GError **error)
1377 user = lightdm_greeter_get_autologin_user_hint (greeter);
1378 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1379 return lightdm_greeter_authenticate_as_guest (greeter, error);
1381 return lightdm_greeter_authenticate (greeter, user, error);
1384 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN,
1385 "Can't authenticate autologin; autologin not configured");
1391 * lightdm_greeter_authenticate_remote:
1392 * @greeter: A #LightDMGreeter
1393 * @session: The name of a remote session
1394 * @username: (allow-none): A username of #NULL to prompt for a username.
1395 * @error: return location for a #GError, or %NULL
1397 * Start authentication for a remote session type.
1399 * Return value: #TRUE if authentication request sent.
1402 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username, GError **error)
1404 LightDMGreeterPrivate *priv;
1405 guint8 message[MAX_MESSAGE_LENGTH];
1408 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1410 priv = GET_PRIVATE (greeter);
1412 g_return_val_if_fail (priv->connected, FALSE);
1414 priv->cancelling_authentication = FALSE;
1415 priv->authenticate_sequence_number++;
1416 priv->in_authentication = TRUE;
1417 priv->is_authenticated = FALSE;
1418 g_free (priv->authentication_user);
1419 priv->authentication_user = NULL;
1422 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1424 g_debug ("Starting authentication for remote session %s...", session);
1426 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset, error) &&
1427 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1428 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
1429 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1430 send_message (greeter, message, offset, error);
1434 * lightdm_greeter_respond:
1435 * @greeter: A #LightDMGreeter
1436 * @response: Response to a prompt
1437 * @error: return location for a #GError, or %NULL
1439 * Provide response to a prompt. May be one in a series.
1441 * Return value: #TRUE if response sent.
1444 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response, GError **error)
1446 LightDMGreeterPrivate *priv;
1447 guint8 message[MAX_MESSAGE_LENGTH];
1450 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1451 g_return_val_if_fail (response != NULL, FALSE);
1453 priv = GET_PRIVATE (greeter);
1455 g_return_val_if_fail (priv->connected, FALSE);
1456 g_return_val_if_fail (priv->n_responses_waiting > 0, FALSE);
1458 priv->n_responses_waiting--;
1459 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1461 if (priv->n_responses_waiting == 0)
1466 g_debug ("Providing response to display manager");
1468 msg_length = int_length ();
1469 for (iter = priv->responses_received; iter; iter = iter->next)
1470 msg_length += string_length ((gchar *)iter->data);
1472 if (!write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset, error) ||
1473 !write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset, error))
1475 for (iter = priv->responses_received; iter; iter = iter->next)
1477 if (!write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset, error))
1480 if (!send_message (greeter, message, offset, error))
1483 g_list_free_full (priv->responses_received, g_free);
1484 priv->responses_received = NULL;
1491 * lightdm_greeter_cancel_authentication:
1492 * @greeter: A #LightDMGreeter
1493 * @error: return location for a #GError, or %NULL
1495 * Cancel the current user authentication.
1497 * Return value: #TRUE if cancel request sent.
1500 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter, GError **error)
1502 LightDMGreeterPrivate *priv;
1503 guint8 message[MAX_MESSAGE_LENGTH];
1506 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1508 priv = GET_PRIVATE (greeter);
1510 g_return_val_if_fail (priv->connected, FALSE);
1512 priv->cancelling_authentication = TRUE;
1513 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset, error) &&
1514 send_message (greeter, message, offset, error);
1518 * lightdm_greeter_get_in_authentication:
1519 * @greeter: A #LightDMGreeter
1521 * Checks if the greeter is in the process of authenticating.
1523 * Return value: #TRUE if the greeter is authenticating a user.
1526 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1528 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1529 return GET_PRIVATE (greeter)->in_authentication;
1533 * lightdm_greeter_get_is_authenticated:
1534 * @greeter: A #LightDMGreeter
1536 * Checks if the greeter has successfully authenticated.
1538 * Return value: #TRUE if the greeter is authenticated for login.
1541 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1543 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1544 return GET_PRIVATE (greeter)->is_authenticated;
1548 * lightdm_greeter_get_authentication_user:
1549 * @greeter: A #LightDMGreeter
1551 * Get the user that is being authenticated.
1553 * Return value: (nullable): The username of the authentication user being authenticated or #NULL if no authentication in progress.
1556 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1558 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1559 return GET_PRIVATE (greeter)->authentication_user;
1563 * lightdm_greeter_set_language:
1564 * @greeter: A #LightDMGreeter
1565 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1566 * @error: return location for a #GError, or %NULL
1568 * Set the language for the currently authenticated user.
1570 * Return value: #TRUE if set language request sent.
1573 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language, GError **error)
1575 LightDMGreeterPrivate *priv;
1576 guint8 message[MAX_MESSAGE_LENGTH];
1579 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1581 priv = GET_PRIVATE (greeter);
1583 g_return_val_if_fail (priv->connected, FALSE);
1585 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset, error) &&
1586 write_string (message, MAX_MESSAGE_LENGTH, language, &offset, error) &&
1587 send_message (greeter, message, offset, error);
1591 * lightdm_greeter_start_session:
1592 * @greeter: A #LightDMGreeter
1593 * @session: (allow-none): The session to log into or #NULL to use the default.
1594 * @cancellable: (allow-none): A #GCancellable or %NULL.
1595 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1596 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1598 * Asynchronously start a session for the authenticated user.
1600 * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_start_session_finish() to get the result of the operation.
1602 * See lightdm_greeter_start_session_sync() for the synchronous version.
1605 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1607 LightDMGreeterPrivate *priv;
1609 GError *error = NULL;
1611 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1613 priv = GET_PRIVATE (greeter);
1615 request = request_new (greeter, cancellable, callback, user_data);
1616 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1617 if (!send_start_session (greeter, session, &error))
1619 request->error = error;
1620 request_complete (request);
1625 * lightdm_greeter_start_session_finish:
1626 * @greeter: A #LightDMGreeter
1627 * @result: A #GAsyncResult.
1628 * @error: return location for a #GError, or %NULL
1630 * Start a session for the authenticated user.
1632 * Return value: TRUE if the session was started.
1635 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1637 Request *request = REQUEST (result);
1639 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1642 g_propagate_error (error, request->error);
1643 return request->result;
1647 * lightdm_greeter_start_session_sync:
1648 * @greeter: A #LightDMGreeter
1649 * @session: (allow-none): The session to log into or #NULL to use the default.
1650 * @error: return location for a #GError, or %NULL
1652 * Start a session for the authenticated user.
1654 * Return value: TRUE if the session was started.
1657 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1659 LightDMGreeterPrivate *priv;
1662 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1664 priv = GET_PRIVATE (greeter);
1666 g_return_val_if_fail (priv->connected, FALSE);
1667 g_return_val_if_fail (priv->is_authenticated, FALSE);
1669 /* Read until the session is started */
1670 if (!send_start_session (greeter, session, error))
1672 request = request_new (greeter, NULL, NULL, NULL);
1673 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1677 gsize message_length;
1679 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1681 handle_message (greeter, message, message_length);
1683 } while (!request->complete);
1685 return lightdm_greeter_start_session_finish (greeter, G_ASYNC_RESULT (request), error);
1689 * lightdm_greeter_ensure_shared_data_dir:
1690 * @greeter: A #LightDMGreeter
1691 * @username: A username
1692 * @cancellable: (allow-none): A #GCancellable or %NULL.
1693 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1694 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1696 * Ensure that a shared data dir for the given user is available. Both the
1697 * greeter user and @username will have write access to that folder. The
1698 * intention is that larger pieces of shared data would be stored there (files
1699 * that the greeter creates but wants to give to a user -- like camera
1700 * photos -- or files that the user creates but wants the greeter to
1701 * see -- like contact avatars).
1703 * LightDM will automatically create these if the user actually logs in, so
1704 * greeters only need to call this method if they want to store something in
1705 * the directory themselves.
1708 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1710 LightDMGreeterPrivate *priv;
1712 GError *error = NULL;
1714 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1716 priv = GET_PRIVATE (greeter);
1718 request = request_new (greeter, cancellable, callback, user_data);
1719 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1720 if (!send_ensure_shared_data_dir (greeter, username, &error))
1722 request->error = error;
1723 request_complete (request);
1728 * lightdm_greeter_ensure_shared_data_dir_finish:
1729 * @result: A #GAsyncResult.
1730 * @greeter: A #LightDMGreeter
1731 * @error: return location for a #GError, or %NULL
1733 * Function to call from lightdm_greeter_ensure_shared_data_dir callback.
1735 * Return value: The path to the shared directory, free with g_free.
1738 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1740 Request *request = REQUEST (result);
1742 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1745 g_propagate_error (error, request->error);
1746 return g_strdup (request->dir);
1750 * lightdm_greeter_ensure_shared_data_dir_sync:
1751 * @greeter: A #LightDMGreeter
1752 * @username: A username
1753 * @error: return location for a #GError, or %NULL
1755 * Ensure that a shared data dir for the given user is available. Both the
1756 * greeter user and @username will have write access to that folder. The
1757 * intention is that larger pieces of shared data would be stored there (files
1758 * that the greeter creates but wants to give to a user -- like camera
1759 * photos -- or files that the user creates but wants the greeter to
1760 * see -- like contact avatars).
1762 * LightDM will automatically create these if the user actually logs in, so
1763 * greeters only need to call this method if they want to store something in
1764 * the directory themselves.
1766 * Return value: The path to the shared directory, free with g_free.
1769 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username, GError **error)
1771 LightDMGreeterPrivate *priv;
1774 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1776 priv = GET_PRIVATE (greeter);
1778 g_return_val_if_fail (priv->connected, NULL);
1780 /* Read until a response */
1781 if (!send_ensure_shared_data_dir (greeter, username, error))
1783 request = request_new (greeter, NULL, NULL, NULL);
1784 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1788 gsize message_length;
1790 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1792 handle_message (greeter, message, message_length);
1794 } while (!request->complete);
1796 return lightdm_greeter_ensure_shared_data_dir_finish (greeter, G_ASYNC_RESULT (request), error);
1800 lightdm_greeter_init (LightDMGreeter *greeter)
1802 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1804 priv->read_buffer = g_malloc (HEADER_SIZE);
1805 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1809 lightdm_greeter_set_property (GObject *object,
1811 const GValue *value,
1814 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1818 lightdm_greeter_get_property (GObject *object,
1823 LightDMGreeter *self;
1825 self = LIGHTDM_GREETER (object);
1828 case PROP_DEFAULT_SESSION_HINT:
1829 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1831 case PROP_HIDE_USERS_HINT:
1832 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1834 case PROP_SHOW_MANUAL_LOGIN_HINT:
1835 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1837 case PROP_SHOW_REMOTE_LOGIN_HINT:
1838 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1840 case PROP_LOCK_HINT:
1841 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1843 case PROP_HAS_GUEST_ACCOUNT_HINT:
1844 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1846 case PROP_SELECT_USER_HINT:
1847 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1849 case PROP_SELECT_GUEST_HINT:
1850 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1852 case PROP_AUTOLOGIN_USER_HINT:
1853 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1855 case PROP_AUTOLOGIN_GUEST_HINT:
1856 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1858 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1859 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1861 case PROP_AUTHENTICATION_USER:
1862 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1864 case PROP_IN_AUTHENTICATION:
1865 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1867 case PROP_IS_AUTHENTICATED:
1868 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1871 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1877 lightdm_greeter_finalize (GObject *object)
1879 LightDMGreeter *self = LIGHTDM_GREETER (object);
1880 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1882 g_clear_object (&priv->socket);
1883 if (priv->to_server_channel)
1884 g_io_channel_unref (priv->to_server_channel);
1885 if (priv->from_server_channel)
1886 g_io_channel_unref (priv->from_server_channel);
1887 g_free (priv->authentication_user);
1888 g_hash_table_unref (priv->hints);
1890 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1894 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1896 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1898 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1900 object_class->set_property = lightdm_greeter_set_property;
1901 object_class->get_property = lightdm_greeter_get_property;
1902 object_class->finalize = lightdm_greeter_finalize;
1904 g_object_class_install_property (object_class,
1905 PROP_DEFAULT_SESSION_HINT,
1906 g_param_spec_string ("default-session-hint",
1907 "default-session-hint",
1908 "Default session hint",
1912 g_object_class_install_property (object_class,
1913 PROP_HIDE_USERS_HINT,
1914 g_param_spec_boolean ("hide-users-hint",
1920 g_object_class_install_property (object_class,
1921 PROP_SHOW_MANUAL_LOGIN_HINT,
1922 g_param_spec_boolean ("show-manual-login-hint",
1923 "show-manual-login-hint",
1924 "Show manual login hint",
1928 g_object_class_install_property (object_class,
1929 PROP_SHOW_REMOTE_LOGIN_HINT,
1930 g_param_spec_boolean ("show-remote-login-hint",
1931 "show-remote-login-hint",
1932 "Show remote login hint",
1936 g_object_class_install_property (object_class,
1938 g_param_spec_boolean ("lock-hint",
1944 g_object_class_install_property (object_class,
1945 PROP_HAS_GUEST_ACCOUNT_HINT,
1946 g_param_spec_boolean ("has-guest-account-hint",
1947 "has-guest-account-hint",
1948 "Has guest account hint",
1952 g_object_class_install_property (object_class,
1953 PROP_SELECT_USER_HINT,
1954 g_param_spec_string ("select-user-hint",
1960 g_object_class_install_property (object_class,
1961 PROP_SELECT_GUEST_HINT,
1962 g_param_spec_boolean ("select-guest-hint",
1963 "select-guest-hint",
1964 "Select guest account hint",
1968 g_object_class_install_property (object_class,
1969 PROP_AUTOLOGIN_USER_HINT,
1970 g_param_spec_string ("autologin-user-hint",
1971 "autologin-user-hint",
1972 "Autologin user hint",
1976 g_object_class_install_property (object_class,
1977 PROP_AUTOLOGIN_GUEST_HINT,
1978 g_param_spec_boolean ("autologin-guest-hint",
1979 "autologin-guest-hint",
1980 "Autologin guest account hint",
1984 g_object_class_install_property (object_class,
1985 PROP_AUTOLOGIN_TIMEOUT_HINT,
1986 g_param_spec_int ("autologin-timeout-hint",
1987 "autologin-timeout-hint",
1988 "Autologin timeout hint",
1992 g_object_class_install_property (object_class,
1993 PROP_AUTHENTICATION_USER,
1994 g_param_spec_string ("authentication-user",
1995 "authentication-user",
1996 "The user being authenticated",
1999 g_object_class_install_property (object_class,
2000 PROP_IN_AUTHENTICATION,
2001 g_param_spec_boolean ("in-authentication",
2002 "in-authentication",
2003 "TRUE if a user is being authenticated",
2006 g_object_class_install_property (object_class,
2007 PROP_IS_AUTHENTICATED,
2008 g_param_spec_boolean ("is-authenticated",
2010 "TRUE if the selected user is authenticated",
2015 * LightDMGreeter::show-prompt:
2016 * @greeter: A #LightDMGreeter
2017 * @text: Prompt text
2018 * @type: Prompt type
2020 * The ::show-prompt signal gets emitted when the greeter should show a
2021 * prompt to the user. The given text should be displayed and an input
2022 * field for the user to provide a response.
2024 * Call lightdm_greeter_respond() with the resultant input or
2025 * lightdm_greeter_cancel_authentication() to abort the authentication.
2027 signals[SHOW_PROMPT] =
2028 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
2029 G_TYPE_FROM_CLASS (klass),
2031 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
2034 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_prompt_type_get_type ());
2037 * LightDMGreeter::show-message:
2038 * @greeter: A #LightDMGreeter
2039 * @text: Message text
2040 * @type: Message type
2042 * The ::show-message signal gets emitted when the greeter
2043 * should show a message to the user.
2045 signals[SHOW_MESSAGE] =
2046 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
2047 G_TYPE_FROM_CLASS (klass),
2049 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
2052 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_message_type_get_type ());
2055 * LightDMGreeter::authentication-complete:
2056 * @greeter: A #LightDMGreeter
2058 * The ::authentication-complete signal gets emitted when the greeter
2059 * has completed authentication.
2061 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
2064 signals[AUTHENTICATION_COMPLETE] =
2065 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
2066 G_TYPE_FROM_CLASS (klass),
2068 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
2074 * LightDMGreeter::autologin-timer-expired:
2075 * @greeter: A #LightDMGreeter
2077 * The ::timed-login signal gets emitted when the automatic login timer has expired.
2078 * The application should then call lightdm_greeter_login().
2080 signals[AUTOLOGIN_TIMER_EXPIRED] =
2081 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
2082 G_TYPE_FROM_CLASS (klass),
2084 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
2090 * LightDMGreeter::idle:
2091 * @greeter: A #LightDMGreeter
2093 * The ::idle signal gets emitted when the user has logged in and the
2094 * greeter is no longer needed.
2096 * This signal only matters if the greeter has marked itself as
2097 * resettable using lightdm_greeter_set_resettable().
2100 g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
2101 G_TYPE_FROM_CLASS (klass),
2103 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
2109 * LightDMGreeter::reset:
2110 * @greeter: A #LightDMGreeter
2112 * The ::reset signal gets emitted when the user is returning to a greeter
2113 * that was previously marked idle.
2115 * This signal only matters if the greeter has marked itself as
2116 * resettable using lightdm_greeter_set_resettable().
2119 g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
2120 G_TYPE_FROM_CLASS (klass),
2122 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
2129 request_init (Request *request)
2134 request_finalize (GObject *object)
2136 Request *request = REQUEST (object);
2138 g_clear_object (&request->greeter);
2139 g_clear_object (&request->cancellable);
2140 g_free (request->dir);
2142 G_OBJECT_CLASS (request_parent_class)->finalize (object);
2146 request_class_init (RequestClass *klass)
2148 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2149 object_class->finalize = request_finalize;
2153 request_get_user_data (GAsyncResult *result)
2155 return REQUEST (result)->user_data;
2159 request_get_source_object (GAsyncResult *result)
2161 return g_object_ref (REQUEST (result)->greeter);
2165 request_iface_init (GAsyncResultIface *iface)
2167 iface->get_user_data = request_get_user_data;
2168 iface->get_source_object = request_get_source_object;