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);
980 g_propagate_error (error, request->error);
981 return request->result;
985 * lightdm_greeter_connect_to_daemon_sync:
986 * @greeter: The greeter to connect
987 * @error: return location for a #GError, or %NULL
989 * Connects the greeter to the display manager. Will block until connected.
991 * Return value: #TRUE if successfully connected
994 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
996 LightDMGreeterPrivate *priv;
999 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1001 priv = GET_PRIVATE (greeter);
1003 /* Read until we are connected */
1004 if (!send_connect (greeter, priv->resettable, error))
1006 request = request_new (greeter, NULL, NULL, NULL);
1007 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
1011 gsize message_length;
1013 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1015 handle_message (greeter, message, message_length);
1017 } while (!request->complete);
1019 return lightdm_greeter_connect_to_daemon_finish (greeter, G_ASYNC_RESULT (request), error);
1023 * lightdm_greeter_connect_sync:
1024 * @greeter: The greeter to connect
1025 * @error: return location for a #GError, or %NULL
1027 * Connects the greeter to the display manager. Will block until connected.
1029 * Return value: #TRUE if successfully connected
1031 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
1034 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
1036 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
1040 * lightdm_greeter_get_hint:
1041 * @greeter: A #LightDMGreeter
1042 * @name: The hint name to query.
1046 * Return value: (nullable): The value for this hint or #NULL if not set.
1049 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
1051 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1052 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
1056 * lightdm_greeter_get_default_session_hint:
1057 * @greeter: A #LightDMGreeter
1059 * Get the default session to use.
1061 * Return value: The session name
1064 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
1066 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1067 return lightdm_greeter_get_hint (greeter, "default-session");
1071 * lightdm_greeter_get_hide_users_hint:
1072 * @greeter: A #LightDMGreeter
1074 * Check if user accounts should be shown. If this is TRUE then the list of
1075 * accounts should be taken from #LightDMUserList and displayed in the greeter
1076 * for the user to choose from. Note that this list can be empty and it is
1077 * recommended you show a method for the user to enter a username manually.
1079 * If this option is shown the greeter should only allow these users to be
1080 * chosen for login unless the manual login hint is set.
1082 * Return value: #TRUE if the available users should not be shown.
1085 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
1089 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1090 value = lightdm_greeter_get_hint (greeter, "hide-users");
1092 return g_strcmp0 (value, "true") == 0;
1096 * lightdm_greeter_get_show_manual_login_hint:
1097 * @greeter: A #LightDMGreeter
1099 * Check if a manual login option should be shown. If set the GUI
1100 * should provide a way for a username to be entered manually.
1101 * Without this hint a greeter which is showing a user list can
1102 * limit logins to only those users.
1104 * Return value: #TRUE if a manual login option should be shown.
1107 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
1111 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1112 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
1114 return g_strcmp0 (value, "true") == 0;
1118 * lightdm_greeter_get_show_remote_login_hint:
1119 * @greeter: A #LightDMGreeter
1121 * Check if a remote login option should be shown. If set the GUI
1122 * should provide a way for a user to log into a remote desktop server.
1124 * Return value: #TRUE if a remote login option should be shown.
1127 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
1131 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1132 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
1134 return g_strcmp0 (value, "true") == 0;
1138 * lightdm_greeter_get_lock_hint:
1139 * @greeter: A #LightDMGreeter
1141 * Check if the greeter is acting as a lock screen.
1143 * Return value: #TRUE if the greeter was triggered by locking the seat.
1146 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
1150 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1151 value = lightdm_greeter_get_hint (greeter, "lock-screen");
1153 return g_strcmp0 (value, "true") == 0;
1157 * lightdm_greeter_get_has_guest_account_hint:
1158 * @greeter: A #LightDMGreeter
1160 * Check if guest sessions are supported.
1162 * Return value: #TRUE if guest sessions are supported.
1165 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
1169 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1170 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
1172 return g_strcmp0 (value, "true") == 0;
1176 * lightdm_greeter_get_select_user_hint:
1177 * @greeter: A #LightDMGreeter
1179 * Get the user to select by default.
1181 * Return value: (nullable): A username or %NULL if no particular user should be selected.
1184 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
1186 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1187 return lightdm_greeter_get_hint (greeter, "select-user");
1191 * lightdm_greeter_get_select_guest_hint:
1192 * @greeter: A #LightDMGreeter
1194 * Check if the guest account should be selected by default.
1196 * Return value: #TRUE if the guest account should be selected by default.
1199 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1203 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1204 value = lightdm_greeter_get_hint (greeter, "select-guest");
1206 return g_strcmp0 (value, "true") == 0;
1210 * lightdm_greeter_get_autologin_user_hint:
1211 * @greeter: A #LightDMGreeter
1213 * Get the user account to automatically log into when the timer expires.
1215 * Return value: (nullable): The user account to automatically log into or %NULL if none configured.
1218 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1220 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1221 return lightdm_greeter_get_hint (greeter, "autologin-user");
1225 * lightdm_greeter_get_autologin_guest_hint:
1226 * @greeter: A #LightDMGreeter
1228 * Check if the guest account should be automatically logged into when the timer expires.
1230 * Return value: #TRUE if the guest account should be automatically logged into.
1233 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1237 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1238 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1240 return g_strcmp0 (value, "true") == 0;
1244 * lightdm_greeter_get_autologin_timeout_hint:
1245 * @greeter: A #LightDMGreeter
1247 * Get the number of seconds to wait before automaitcally logging in.
1249 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1252 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1257 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1258 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1260 timeout = atoi (value);
1268 * lightdm_greeter_cancel_autologin:
1269 * @greeter: A #LightDMGreeter
1271 * Cancel the automatic login.
1274 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1276 LightDMGreeterPrivate *priv;
1278 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1280 priv = GET_PRIVATE (greeter);
1282 if (priv->autologin_timeout)
1283 g_source_remove (priv->autologin_timeout);
1284 priv->autologin_timeout = 0;
1288 * lightdm_greeter_authenticate:
1289 * @greeter: A #LightDMGreeter
1290 * @username: (allow-none): A username or #NULL to prompt for a username.
1291 * @error: return location for a #GError, or %NULL
1293 * Starts the authentication procedure for a user.
1295 * Return value: #TRUE if authentication request sent.
1298 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username, GError **error)
1300 LightDMGreeterPrivate *priv;
1301 guint8 message[MAX_MESSAGE_LENGTH];
1304 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1306 priv = GET_PRIVATE (greeter);
1308 g_return_val_if_fail (priv->connected, FALSE);
1310 priv->cancelling_authentication = FALSE;
1311 priv->authenticate_sequence_number++;
1312 priv->in_authentication = TRUE;
1313 priv->is_authenticated = FALSE;
1314 if (username != priv->authentication_user)
1316 g_free (priv->authentication_user);
1317 priv->authentication_user = g_strdup (username);
1320 g_debug ("Starting authentication for user %s...", username);
1321 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset, error) &&
1322 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1323 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1324 send_message (greeter, message, offset, error);
1328 * lightdm_greeter_authenticate_as_guest:
1329 * @greeter: A #LightDMGreeter
1330 * @error: return location for a #GError, or %NULL
1332 * Starts the authentication procedure for the guest user.
1334 * Return value: #TRUE if authentication request sent.
1337 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter, GError **error)
1339 LightDMGreeterPrivate *priv;
1340 guint8 message[MAX_MESSAGE_LENGTH];
1343 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1345 priv = GET_PRIVATE (greeter);
1347 g_return_val_if_fail (priv->connected, FALSE);
1349 priv->cancelling_authentication = FALSE;
1350 priv->authenticate_sequence_number++;
1351 priv->in_authentication = TRUE;
1352 priv->is_authenticated = FALSE;
1353 g_free (priv->authentication_user);
1354 priv->authentication_user = NULL;
1356 g_debug ("Starting authentication for guest account...");
1357 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset, error) &&
1358 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1359 send_message (greeter, message, offset, error);
1363 * lightdm_greeter_authenticate_autologin:
1364 * @greeter: A #LightDMGreeter
1365 * @error: return location for a #GError, or %NULL
1367 * Starts the authentication procedure for the automatic login user.
1369 * Return value: #TRUE if authentication request sent.
1372 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter, GError **error)
1376 user = lightdm_greeter_get_autologin_user_hint (greeter);
1377 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1378 return lightdm_greeter_authenticate_as_guest (greeter, error);
1380 return lightdm_greeter_authenticate (greeter, user, error);
1383 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN,
1384 "Can't authenticate autologin; autologin not configured");
1390 * lightdm_greeter_authenticate_remote:
1391 * @greeter: A #LightDMGreeter
1392 * @session: The name of a remote session
1393 * @username: (allow-none): A username of #NULL to prompt for a username.
1394 * @error: return location for a #GError, or %NULL
1396 * Start authentication for a remote session type.
1398 * Return value: #TRUE if authentication request sent.
1401 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username, GError **error)
1403 LightDMGreeterPrivate *priv;
1404 guint8 message[MAX_MESSAGE_LENGTH];
1407 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1409 priv = GET_PRIVATE (greeter);
1411 g_return_val_if_fail (priv->connected, FALSE);
1413 priv->cancelling_authentication = FALSE;
1414 priv->authenticate_sequence_number++;
1415 priv->in_authentication = TRUE;
1416 priv->is_authenticated = FALSE;
1417 g_free (priv->authentication_user);
1418 priv->authentication_user = NULL;
1421 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1423 g_debug ("Starting authentication for remote session %s...", session);
1425 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset, error) &&
1426 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1427 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
1428 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1429 send_message (greeter, message, offset, error);
1433 * lightdm_greeter_respond:
1434 * @greeter: A #LightDMGreeter
1435 * @response: Response to a prompt
1436 * @error: return location for a #GError, or %NULL
1438 * Provide response to a prompt. May be one in a series.
1440 * Return value: #TRUE if response sent.
1443 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response, GError **error)
1445 LightDMGreeterPrivate *priv;
1446 guint8 message[MAX_MESSAGE_LENGTH];
1449 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1450 g_return_val_if_fail (response != NULL, FALSE);
1452 priv = GET_PRIVATE (greeter);
1454 g_return_val_if_fail (priv->connected, FALSE);
1455 g_return_val_if_fail (priv->n_responses_waiting > 0, FALSE);
1457 priv->n_responses_waiting--;
1458 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1460 if (priv->n_responses_waiting == 0)
1465 g_debug ("Providing response to display manager");
1467 msg_length = int_length ();
1468 for (iter = priv->responses_received; iter; iter = iter->next)
1469 msg_length += string_length ((gchar *)iter->data);
1471 if (!write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset, error) ||
1472 !write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset, error))
1474 for (iter = priv->responses_received; iter; iter = iter->next)
1476 if (!write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset, error))
1479 if (!send_message (greeter, message, offset, error))
1482 g_list_free_full (priv->responses_received, g_free);
1483 priv->responses_received = NULL;
1490 * lightdm_greeter_cancel_authentication:
1491 * @greeter: A #LightDMGreeter
1492 * @error: return location for a #GError, or %NULL
1494 * Cancel the current user authentication.
1496 * Return value: #TRUE if cancel request sent.
1499 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter, GError **error)
1501 LightDMGreeterPrivate *priv;
1502 guint8 message[MAX_MESSAGE_LENGTH];
1505 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1507 priv = GET_PRIVATE (greeter);
1509 g_return_val_if_fail (priv->connected, FALSE);
1511 priv->cancelling_authentication = TRUE;
1512 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset, error) &&
1513 send_message (greeter, message, offset, error);
1517 * lightdm_greeter_get_in_authentication:
1518 * @greeter: A #LightDMGreeter
1520 * Checks if the greeter is in the process of authenticating.
1522 * Return value: #TRUE if the greeter is authenticating a user.
1525 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1527 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1528 return GET_PRIVATE (greeter)->in_authentication;
1532 * lightdm_greeter_get_is_authenticated:
1533 * @greeter: A #LightDMGreeter
1535 * Checks if the greeter has successfully authenticated.
1537 * Return value: #TRUE if the greeter is authenticated for login.
1540 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1542 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1543 return GET_PRIVATE (greeter)->is_authenticated;
1547 * lightdm_greeter_get_authentication_user:
1548 * @greeter: A #LightDMGreeter
1550 * Get the user that is being authenticated.
1552 * Return value: (nullable): The username of the authentication user being authenticated or #NULL if no authentication in progress.
1555 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1557 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1558 return GET_PRIVATE (greeter)->authentication_user;
1562 * lightdm_greeter_set_language:
1563 * @greeter: A #LightDMGreeter
1564 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1565 * @error: return location for a #GError, or %NULL
1567 * Set the language for the currently authenticated user.
1569 * Return value: #TRUE if set language request sent.
1572 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language, GError **error)
1574 LightDMGreeterPrivate *priv;
1575 guint8 message[MAX_MESSAGE_LENGTH];
1578 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1580 priv = GET_PRIVATE (greeter);
1582 g_return_val_if_fail (priv->connected, FALSE);
1584 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset, error) &&
1585 write_string (message, MAX_MESSAGE_LENGTH, language, &offset, error) &&
1586 send_message (greeter, message, offset, error);
1590 * lightdm_greeter_start_session:
1591 * @greeter: A #LightDMGreeter
1592 * @session: (allow-none): The session to log into or #NULL to use the default.
1593 * @cancellable: (allow-none): A #GCancellable or %NULL.
1594 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1595 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1597 * Asynchronously start a session for the authenticated user.
1599 * 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.
1601 * See lightdm_greeter_start_session_sync() for the synchronous version.
1604 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1606 LightDMGreeterPrivate *priv;
1608 GError *error = NULL;
1610 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1612 priv = GET_PRIVATE (greeter);
1614 request = request_new (greeter, cancellable, callback, user_data);
1615 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1616 if (!send_start_session (greeter, session, &error))
1618 request->error = error;
1619 request_complete (request);
1624 * lightdm_greeter_start_session_finish:
1625 * @greeter: A #LightDMGreeter
1626 * @result: A #GAsyncResult.
1627 * @error: return location for a #GError, or %NULL
1629 * Start a session for the authenticated user.
1631 * Return value: TRUE if the session was started.
1634 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1636 Request *request = REQUEST (result);
1638 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1640 g_propagate_error (error, request->error);
1641 return request->result;
1645 * lightdm_greeter_start_session_sync:
1646 * @greeter: A #LightDMGreeter
1647 * @session: (allow-none): The session to log into or #NULL to use the default.
1648 * @error: return location for a #GError, or %NULL
1650 * Start a session for the authenticated user.
1652 * Return value: TRUE if the session was started.
1655 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1657 LightDMGreeterPrivate *priv;
1660 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1662 priv = GET_PRIVATE (greeter);
1664 g_return_val_if_fail (priv->connected, FALSE);
1665 g_return_val_if_fail (priv->is_authenticated, FALSE);
1667 /* Read until the session is started */
1668 if (!send_start_session (greeter, session, error))
1670 request = request_new (greeter, NULL, NULL, NULL);
1671 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1675 gsize message_length;
1677 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1679 handle_message (greeter, message, message_length);
1681 } while (!request->complete);
1683 return lightdm_greeter_start_session_finish (greeter, G_ASYNC_RESULT (request), error);
1687 * lightdm_greeter_ensure_shared_data_dir:
1688 * @greeter: A #LightDMGreeter
1689 * @username: A username
1690 * @cancellable: (allow-none): A #GCancellable or %NULL.
1691 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1692 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1694 * Ensure that a shared data dir for the given user is available. Both the
1695 * greeter user and @username will have write access to that folder. The
1696 * intention is that larger pieces of shared data would be stored there (files
1697 * that the greeter creates but wants to give to a user -- like camera
1698 * photos -- or files that the user creates but wants the greeter to
1699 * see -- like contact avatars).
1701 * LightDM will automatically create these if the user actually logs in, so
1702 * greeters only need to call this method if they want to store something in
1703 * the directory themselves.
1706 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1708 LightDMGreeterPrivate *priv;
1710 GError *error = NULL;
1712 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1714 priv = GET_PRIVATE (greeter);
1716 request = request_new (greeter, cancellable, callback, user_data);
1717 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1718 if (!send_ensure_shared_data_dir (greeter, username, &error))
1720 request->error = error;
1721 request_complete (request);
1726 * lightdm_greeter_ensure_shared_data_dir_finish:
1727 * @result: A #GAsyncResult.
1728 * @greeter: A #LightDMGreeter
1729 * @error: return location for a #GError, or %NULL
1731 * Function to call from lightdm_greeter_ensure_shared_data_dir callback.
1733 * Return value: The path to the shared directory, free with g_free.
1736 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1738 Request *request = REQUEST (result);
1740 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1742 g_propagate_error (error, request->error);
1743 return g_strdup (request->dir);
1747 * lightdm_greeter_ensure_shared_data_dir_sync:
1748 * @greeter: A #LightDMGreeter
1749 * @username: A username
1750 * @error: return location for a #GError, or %NULL
1752 * Ensure that a shared data dir for the given user is available. Both the
1753 * greeter user and @username will have write access to that folder. The
1754 * intention is that larger pieces of shared data would be stored there (files
1755 * that the greeter creates but wants to give to a user -- like camera
1756 * photos -- or files that the user creates but wants the greeter to
1757 * see -- like contact avatars).
1759 * LightDM will automatically create these if the user actually logs in, so
1760 * greeters only need to call this method if they want to store something in
1761 * the directory themselves.
1763 * Return value: The path to the shared directory, free with g_free.
1766 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username, GError **error)
1768 LightDMGreeterPrivate *priv;
1771 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1773 priv = GET_PRIVATE (greeter);
1775 g_return_val_if_fail (priv->connected, NULL);
1777 /* Read until a response */
1778 if (!send_ensure_shared_data_dir (greeter, username, error))
1780 request = request_new (greeter, NULL, NULL, NULL);
1781 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1785 gsize message_length;
1787 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1789 handle_message (greeter, message, message_length);
1791 } while (!request->complete);
1793 return lightdm_greeter_ensure_shared_data_dir_finish (greeter, G_ASYNC_RESULT (request), error);
1797 lightdm_greeter_init (LightDMGreeter *greeter)
1799 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1801 priv->read_buffer = g_malloc (HEADER_SIZE);
1802 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1806 lightdm_greeter_set_property (GObject *object,
1808 const GValue *value,
1811 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1815 lightdm_greeter_get_property (GObject *object,
1820 LightDMGreeter *self;
1822 self = LIGHTDM_GREETER (object);
1825 case PROP_DEFAULT_SESSION_HINT:
1826 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1828 case PROP_HIDE_USERS_HINT:
1829 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1831 case PROP_SHOW_MANUAL_LOGIN_HINT:
1832 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1834 case PROP_SHOW_REMOTE_LOGIN_HINT:
1835 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1837 case PROP_LOCK_HINT:
1838 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1840 case PROP_HAS_GUEST_ACCOUNT_HINT:
1841 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1843 case PROP_SELECT_USER_HINT:
1844 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1846 case PROP_SELECT_GUEST_HINT:
1847 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1849 case PROP_AUTOLOGIN_USER_HINT:
1850 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1852 case PROP_AUTOLOGIN_GUEST_HINT:
1853 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1855 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1856 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1858 case PROP_AUTHENTICATION_USER:
1859 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1861 case PROP_IN_AUTHENTICATION:
1862 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1864 case PROP_IS_AUTHENTICATED:
1865 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1868 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1874 lightdm_greeter_finalize (GObject *object)
1876 LightDMGreeter *self = LIGHTDM_GREETER (object);
1877 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1879 g_clear_object (&priv->socket);
1880 if (priv->to_server_channel)
1881 g_io_channel_unref (priv->to_server_channel);
1882 if (priv->from_server_channel)
1883 g_io_channel_unref (priv->from_server_channel);
1884 g_free (priv->authentication_user);
1885 g_hash_table_unref (priv->hints);
1887 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1891 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1893 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1895 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1897 object_class->set_property = lightdm_greeter_set_property;
1898 object_class->get_property = lightdm_greeter_get_property;
1899 object_class->finalize = lightdm_greeter_finalize;
1901 g_object_class_install_property (object_class,
1902 PROP_DEFAULT_SESSION_HINT,
1903 g_param_spec_string ("default-session-hint",
1904 "default-session-hint",
1905 "Default session hint",
1909 g_object_class_install_property (object_class,
1910 PROP_HIDE_USERS_HINT,
1911 g_param_spec_boolean ("hide-users-hint",
1917 g_object_class_install_property (object_class,
1918 PROP_SHOW_MANUAL_LOGIN_HINT,
1919 g_param_spec_boolean ("show-manual-login-hint",
1920 "show-manual-login-hint",
1921 "Show manual login hint",
1925 g_object_class_install_property (object_class,
1926 PROP_SHOW_REMOTE_LOGIN_HINT,
1927 g_param_spec_boolean ("show-remote-login-hint",
1928 "show-remote-login-hint",
1929 "Show remote login hint",
1933 g_object_class_install_property (object_class,
1935 g_param_spec_boolean ("lock-hint",
1941 g_object_class_install_property (object_class,
1942 PROP_HAS_GUEST_ACCOUNT_HINT,
1943 g_param_spec_boolean ("has-guest-account-hint",
1944 "has-guest-account-hint",
1945 "Has guest account hint",
1949 g_object_class_install_property (object_class,
1950 PROP_SELECT_USER_HINT,
1951 g_param_spec_string ("select-user-hint",
1957 g_object_class_install_property (object_class,
1958 PROP_SELECT_GUEST_HINT,
1959 g_param_spec_boolean ("select-guest-hint",
1960 "select-guest-hint",
1961 "Select guest account hint",
1965 g_object_class_install_property (object_class,
1966 PROP_AUTOLOGIN_USER_HINT,
1967 g_param_spec_string ("autologin-user-hint",
1968 "autologin-user-hint",
1969 "Autologin user hint",
1973 g_object_class_install_property (object_class,
1974 PROP_AUTOLOGIN_GUEST_HINT,
1975 g_param_spec_boolean ("autologin-guest-hint",
1976 "autologin-guest-hint",
1977 "Autologin guest account hint",
1981 g_object_class_install_property (object_class,
1982 PROP_AUTOLOGIN_TIMEOUT_HINT,
1983 g_param_spec_int ("autologin-timeout-hint",
1984 "autologin-timeout-hint",
1985 "Autologin timeout hint",
1989 g_object_class_install_property (object_class,
1990 PROP_AUTHENTICATION_USER,
1991 g_param_spec_string ("authentication-user",
1992 "authentication-user",
1993 "The user being authenticated",
1996 g_object_class_install_property (object_class,
1997 PROP_IN_AUTHENTICATION,
1998 g_param_spec_boolean ("in-authentication",
1999 "in-authentication",
2000 "TRUE if a user is being authenticated",
2003 g_object_class_install_property (object_class,
2004 PROP_IS_AUTHENTICATED,
2005 g_param_spec_boolean ("is-authenticated",
2007 "TRUE if the selected user is authenticated",
2012 * LightDMGreeter::show-prompt:
2013 * @greeter: A #LightDMGreeter
2014 * @text: Prompt text
2015 * @type: Prompt type
2017 * The ::show-prompt signal gets emitted when the greeter should show a
2018 * prompt to the user. The given text should be displayed and an input
2019 * field for the user to provide a response.
2021 * Call lightdm_greeter_respond() with the resultant input or
2022 * lightdm_greeter_cancel_authentication() to abort the authentication.
2024 signals[SHOW_PROMPT] =
2025 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
2026 G_TYPE_FROM_CLASS (klass),
2028 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
2031 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_prompt_type_get_type ());
2034 * LightDMGreeter::show-message:
2035 * @greeter: A #LightDMGreeter
2036 * @text: Message text
2037 * @type: Message type
2039 * The ::show-message signal gets emitted when the greeter
2040 * should show a message to the user.
2042 signals[SHOW_MESSAGE] =
2043 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
2044 G_TYPE_FROM_CLASS (klass),
2046 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
2049 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_message_type_get_type ());
2052 * LightDMGreeter::authentication-complete:
2053 * @greeter: A #LightDMGreeter
2055 * The ::authentication-complete signal gets emitted when the greeter
2056 * has completed authentication.
2058 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
2061 signals[AUTHENTICATION_COMPLETE] =
2062 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
2063 G_TYPE_FROM_CLASS (klass),
2065 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
2071 * LightDMGreeter::autologin-timer-expired:
2072 * @greeter: A #LightDMGreeter
2074 * The ::timed-login signal gets emitted when the automatic login timer has expired.
2075 * The application should then call lightdm_greeter_login().
2077 signals[AUTOLOGIN_TIMER_EXPIRED] =
2078 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
2079 G_TYPE_FROM_CLASS (klass),
2081 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
2087 * LightDMGreeter::idle:
2088 * @greeter: A #LightDMGreeter
2090 * The ::idle signal gets emitted when the user has logged in and the
2091 * greeter is no longer needed.
2093 * This signal only matters if the greeter has marked itself as
2094 * resettable using lightdm_greeter_set_resettable().
2097 g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
2098 G_TYPE_FROM_CLASS (klass),
2100 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
2106 * LightDMGreeter::reset:
2107 * @greeter: A #LightDMGreeter
2109 * The ::reset signal gets emitted when the user is returning to a greeter
2110 * that was previously marked idle.
2112 * This signal only matters if the greeter has marked itself as
2113 * resettable using lightdm_greeter_set_resettable().
2116 g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
2117 G_TYPE_FROM_CLASS (klass),
2119 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
2126 request_init (Request *request)
2131 request_finalize (GObject *object)
2133 Request *request = REQUEST (object);
2135 g_clear_object (&request->greeter);
2136 g_clear_object (&request->cancellable);
2137 g_free (request->dir);
2139 G_OBJECT_CLASS (request_parent_class)->finalize (object);
2143 request_class_init (RequestClass *klass)
2145 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2146 object_class->finalize = request_finalize;
2150 request_get_user_data (GAsyncResult *result)
2152 return REQUEST (result)->user_data;
2156 request_get_source_object (GAsyncResult *result)
2158 return g_object_ref (REQUEST (result)->greeter);
2162 request_iface_init (GAsyncResultIface *iface)
2164 iface->get_user_data = request_get_user_data;
2165 iface->get_source_object = request_get_source_object;