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)
24 PROP_DEFAULT_SESSION_HINT = 1,
26 PROP_SHOW_MANUAL_LOGIN_HINT,
27 PROP_SHOW_REMOTE_LOGIN_HINT,
29 PROP_HAS_GUEST_ACCOUNT_HINT,
30 PROP_SELECT_USER_HINT,
31 PROP_SELECT_GUEST_HINT,
32 PROP_AUTOLOGIN_USER_HINT,
33 PROP_AUTOLOGIN_GUEST_HINT,
34 PROP_AUTOLOGIN_TIMEOUT_HINT,
35 PROP_AUTHENTICATION_USER,
36 PROP_IN_AUTHENTICATION,
37 PROP_IS_AUTHENTICATED,
43 AUTHENTICATION_COMPLETE,
44 AUTOLOGIN_TIMER_EXPIRED,
49 static guint signals[LAST_SIGNAL] = { 0 };
53 /* TRUE if the daemon can reuse this greeter */
56 /* Socket connection to daemon */
59 /* Channel to write to daemon */
60 GIOChannel *to_server_channel;
62 /* Channel to read from daemon */
63 GIOChannel *from_server_channel;
64 guint from_server_watch;
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_WITH_PRIVATE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
100 #define HEADER_SIZE 8
101 #define MAX_MESSAGE_LENGTH 1024
103 /* Messages from the greeter to the server */
106 GREETER_MESSAGE_CONNECT = 0,
107 GREETER_MESSAGE_AUTHENTICATE,
108 GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
109 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
110 GREETER_MESSAGE_START_SESSION,
111 GREETER_MESSAGE_CANCEL_AUTHENTICATION,
112 GREETER_MESSAGE_SET_LANGUAGE,
113 GREETER_MESSAGE_AUTHENTICATE_REMOTE,
114 GREETER_MESSAGE_ENSURE_SHARED_DIR,
117 /* Messages from the server to the greeter */
120 SERVER_MESSAGE_CONNECTED = 0,
121 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
122 SERVER_MESSAGE_END_AUTHENTICATION,
123 SERVER_MESSAGE_SESSION_RESULT,
124 SERVER_MESSAGE_SHARED_DIR_RESULT,
126 SERVER_MESSAGE_RESET,
129 /* Request sent to server */
132 GObject parent_instance;
133 LightDMGreeter *greeter;
134 GCancellable *cancellable;
135 GAsyncReadyCallback callback;
144 GObjectClass parent_class;
146 GType request_get_type (void);
147 static void request_iface_init (GAsyncResultIface *iface);
148 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
149 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
151 static gboolean from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data);
154 lightdm_greeter_error_get_type (void)
156 static GType enum_type = 0;
158 if (G_UNLIKELY(enum_type == 0)) {
159 static const GEnumValue values[] = {
160 { LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR, "LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR", "communication-error" },
161 { LIGHTDM_GREETER_ERROR_CONNECTION_FAILED, "LIGHTDM_GREETER_ERROR_CONNECTION_FAILED", "connection-failed" },
162 { LIGHTDM_GREETER_ERROR_SESSION_FAILED, "LIGHTDM_GREETER_ERROR_SESSION_FAILED", "session-failed" },
163 { LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN, "LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN", "no-autologin" },
164 { LIGHTDM_GREETER_ERROR_INVALID_USER, "LIGHTDM_GREETER_ERROR_INVALID_USER", "invalid-user" },
167 enum_type = g_enum_register_static (g_intern_static_string ("LightDMGreeterError"), values);
174 lightdm_prompt_type_get_type (void)
176 static GType enum_type = 0;
178 if (G_UNLIKELY(enum_type == 0)) {
179 static const GEnumValue values[] = {
180 { LIGHTDM_PROMPT_TYPE_QUESTION, "LIGHTDM_PROMPT_TYPE_QUESTION", "question" },
181 { LIGHTDM_PROMPT_TYPE_SECRET, "LIGHTDM_PROMPT_TYPE_SECRET", "secret" },
184 enum_type = g_enum_register_static (g_intern_static_string ("LightDMPromptType"), values);
191 lightdm_message_type_get_type (void)
193 static GType enum_type = 0;
195 if (G_UNLIKELY(enum_type == 0)) {
196 static const GEnumValue values[] = {
197 { LIGHTDM_MESSAGE_TYPE_INFO, "LIGHTDM_MESSAGE_TYPE_INFO", "info" },
198 { LIGHTDM_MESSAGE_TYPE_ERROR, "LIGHTDM_MESSAGE_TYPE_ERROR", "error" },
201 enum_type = g_enum_register_static (g_intern_static_string ("LightDMMessageType"), values);
209 * lightdm_greeter_new:
211 * Create a new greeter.
213 * Return value: the new #LightDMGreeter
216 lightdm_greeter_new (void)
218 return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
222 * lightdm_greeter_set_resettable:
223 * @greeter: A #LightDMGreeter
224 * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
226 * Set whether the greeter will be reset instead of killed after the user logs in.
227 * This must be called before lightdm_greeter_connect is called.
230 lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
232 LightDMGreeterPrivate *priv;
234 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
236 priv = lightdm_greeter_get_instance_private (greeter);
238 g_return_if_fail (!priv->connected);
239 priv->resettable = resettable;
243 request_new (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
247 request = g_object_new (request_get_type (), NULL);
248 request->greeter = greeter;
250 request->cancellable = g_object_ref (cancellable);
251 request->callback = callback;
252 request->user_data = user_data;
258 request_callback_cb (gpointer data)
260 Request *request = data;
261 if (request->callback)
262 request->callback (G_OBJECT (request->greeter), G_ASYNC_RESULT (request), request->user_data);
263 g_object_unref (request);
264 return G_SOURCE_REMOVE;
268 request_complete (Request *request)
270 request->complete = TRUE;
272 if (!request->callback)
275 if (request->cancellable && g_cancellable_is_cancelled (request->cancellable))
278 g_idle_add (request_callback_cb, g_object_ref (request));
282 timed_login_cb (gpointer data)
284 LightDMGreeter *greeter = data;
285 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
287 priv->autologin_timeout = 0;
288 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
300 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset, GError **error)
302 if (*offset + 4 >= buffer_length)
304 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
305 "Not enough buffer space to write integer");
308 buffer[*offset] = value >> 24;
309 buffer[*offset+1] = (value >> 16) & 0xFF;
310 buffer[*offset+2] = (value >> 8) & 0xFF;
311 buffer[*offset+3] = value & 0xFF;
318 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset, GError **error)
323 length = strlen (value);
324 if (!write_int (buffer, buffer_length, length, offset, error))
326 if (*offset + length >= buffer_length)
328 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
329 "Not enough buffer space to write string of length %d octets", length);
333 memcpy (buffer + *offset, value, length);
340 read_int (guint8 *message, gsize message_length, gsize *offset)
345 if (message_length - *offset < int_length ())
347 g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
351 buffer = message + *offset;
352 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
353 *offset += int_length ();
359 read_string (guint8 *message, gsize message_length, gsize *offset)
364 length = read_int (message, message_length, offset);
365 if (message_length - *offset < length)
367 g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
368 return g_strdup ("");
371 value = g_malloc (sizeof (gchar) * (length + 1));
372 memcpy (value, message + *offset, length);
373 value[length] = '\0';
380 string_length (const gchar *value)
383 return int_length () + strlen (value);
385 return int_length ();
389 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset, GError **error)
391 return write_int (buffer, buffer_length, id, offset, error) &&
392 write_int (buffer, buffer_length, length, offset, error);
396 get_message_length (guint8 *message, gsize message_length)
399 return read_int (message, message_length, &offset);
403 connect_to_daemon (LightDMGreeter *greeter, GError **error)
405 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
406 const gchar *to_server_fd, *from_server_fd, *pipe_path;
408 if (priv->to_server_channel || priv->from_server_channel)
411 /* Use private connection if one exists */
412 to_server_fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
413 from_server_fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
414 pipe_path = g_getenv ("LIGHTDM_GREETER_PIPE");
415 if (to_server_fd && from_server_fd)
417 priv->to_server_channel = g_io_channel_unix_new (atoi (to_server_fd));
418 priv->from_server_channel = g_io_channel_unix_new (atoi (from_server_fd));
422 GSocketAddress *address;
425 priv->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error);
429 address = g_unix_socket_address_new (pipe_path);
430 result = g_socket_connect (priv->socket, address, NULL, error);
431 g_object_unref (address);
435 priv->from_server_channel = g_io_channel_unix_new (g_socket_get_fd (priv->socket));
436 priv->to_server_channel = g_io_channel_ref (priv->from_server_channel);
440 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_CONNECTION_FAILED,
441 "Unable to determine socket to daemon");
445 priv->from_server_watch = g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
447 if (!g_io_channel_set_encoding (priv->to_server_channel, NULL, error) ||
448 !g_io_channel_set_encoding (priv->from_server_channel, NULL, error))
455 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length, GError **error)
457 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
460 guint32 stated_length;
461 GError *flush_error = NULL;
463 if (!connect_to_daemon (greeter, error))
466 /* Double check that we're sending well-formed messages. If we say we're
467 sending more than we do, we end up DOS'ing lightdm as it waits for the
468 rest. If we say we're sending less than we do, we confuse the heck out
469 of lightdm, as it starts reading headers from the middle of our
471 stated_length = HEADER_SIZE + get_message_length (message, message_length);
472 if (stated_length != message_length)
474 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
475 "Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu",
476 stated_length, message_length);
480 data = (gchar *) message;
481 data_length = message_length;
482 while (data_length > 0)
486 GError *write_error = NULL;
488 status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &write_error);
490 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
491 "Failed to write to daemon: %s",
492 write_error->message);
493 g_clear_error (&write_error);
494 if (status == G_IO_STATUS_AGAIN)
496 if (status != G_IO_STATUS_NORMAL)
498 data_length -= n_written;
502 g_debug ("Wrote %zi bytes to daemon", message_length);
503 if (!g_io_channel_flush (priv->to_server_channel, &flush_error))
505 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
506 "Failed to write to daemon: %s",
507 flush_error->message);
508 g_clear_error (&flush_error);
516 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
518 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
520 GString *hint_string;
524 version = read_string (message, message_length, offset);
525 hint_string = g_string_new ("");
526 while (*offset < message_length)
530 name = read_string (message, message_length, offset);
531 value = read_string (message, message_length, offset);
532 g_hash_table_insert (priv->hints, name, value);
533 g_string_append_printf (hint_string, " %s=%s", name, value);
536 priv->connected = TRUE;
537 g_debug ("Connected version=%s%s", version, hint_string->str);
539 g_string_free (hint_string, TRUE);
541 /* Set timeout for default login */
542 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
545 g_debug ("Setting autologin timer for %d seconds", timeout);
546 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
549 /* Notify asynchronous caller */
550 request = g_list_nth_data (priv->connect_requests, 0);
553 request->result = TRUE;
554 request_complete (request);
555 priv->connect_requests = g_list_remove (priv->connect_requests, request);
556 g_object_unref (request);
561 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
563 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
564 guint32 sequence_number, n_messages, i;
567 sequence_number = read_int (message, message_length, offset);
568 if (sequence_number != priv->authenticate_sequence_number)
570 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
574 if (priv->cancelling_authentication)
576 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
580 /* Update username */
581 username = read_string (message, message_length, offset);
582 if (strcmp (username, "") == 0)
587 g_free (priv->authentication_user);
588 priv->authentication_user = username;
590 g_list_free_full (priv->responses_received, g_free);
591 priv->responses_received = NULL;
592 priv->n_responses_waiting = 0;
594 n_messages = read_int (message, message_length, offset);
595 g_debug ("Prompt user with %d message(s)", n_messages);
597 for (i = 0; i < n_messages; i++)
602 style = read_int (message, message_length, offset);
603 text = read_string (message, message_length, offset);
605 // FIXME: Should stop on prompts?
608 case PAM_PROMPT_ECHO_OFF:
609 priv->n_responses_waiting++;
610 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
612 case PAM_PROMPT_ECHO_ON:
613 priv->n_responses_waiting++;
614 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
617 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
620 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
629 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
631 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
632 guint32 sequence_number, return_code;
635 sequence_number = read_int (message, message_length, offset);
637 if (sequence_number != priv->authenticate_sequence_number)
639 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
643 username = read_string (message, message_length, offset);
644 return_code = read_int (message, message_length, offset);
646 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
648 /* Update username */
649 if (strcmp (username, "") == 0)
654 g_free (priv->authentication_user);
655 priv->authentication_user = username;
657 priv->cancelling_authentication = FALSE;
658 priv->is_authenticated = (return_code == 0);
660 priv->in_authentication = FALSE;
661 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
665 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
667 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
671 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
673 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
674 GString *hint_string;
676 g_hash_table_remove_all (priv->hints);
678 hint_string = g_string_new ("");
679 while (*offset < message_length)
683 name = read_string (message, message_length, offset);
684 value = read_string (message, message_length, offset);
685 g_hash_table_insert (priv->hints, name, value);
686 g_string_append_printf (hint_string, " %s=%s", name, value);
689 g_debug ("Reset%s", hint_string->str);
690 g_string_free (hint_string, TRUE);
692 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
696 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
698 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
701 /* Notify asynchronous caller */
702 request = g_list_nth_data (priv->start_session_requests, 0);
707 return_code = read_int (message, message_length, offset);
708 if (return_code == 0)
709 request->result = TRUE;
711 request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_SESSION_FAILED,
712 "Session returned error code %d", return_code);
713 request_complete (request);
714 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
715 g_object_unref (request);
720 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
722 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
725 /* Notify asynchronous caller */
726 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
729 request->dir = read_string (message, message_length, offset);
730 /* Blank data dir means invalid user */
731 if (g_strcmp0 (request->dir, "") == 0)
733 g_free (request->dir);
735 request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_INVALID_USER,
738 request_complete (request);
739 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
740 g_object_unref (request);
745 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
750 id = read_int (message, message_length, &offset);
751 read_int (message, message_length, &offset);
754 case SERVER_MESSAGE_CONNECTED:
755 handle_connected (greeter, message, message_length, &offset);
757 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
758 handle_prompt_authentication (greeter, message, message_length, &offset);
760 case SERVER_MESSAGE_END_AUTHENTICATION:
761 handle_end_authentication (greeter, message, message_length, &offset);
763 case SERVER_MESSAGE_SESSION_RESULT:
764 handle_session_result (greeter, message, message_length, &offset);
766 case SERVER_MESSAGE_SHARED_DIR_RESULT:
767 handle_shared_dir_result (greeter, message, message_length, &offset);
769 case SERVER_MESSAGE_IDLE:
770 handle_idle (greeter, message, message_length, &offset);
772 case SERVER_MESSAGE_RESET:
773 handle_reset (greeter, message, message_length, &offset);
776 g_warning ("Unknown message from server: %d", id);
782 recv_message (LightDMGreeter *greeter, gboolean block, guint8 **message, gsize *length, GError **error)
784 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
785 gsize n_to_read, n_read;
787 if (!connect_to_daemon (greeter, error))
790 /* Read the header, or the whole message if we already have that */
791 n_to_read = HEADER_SIZE;
792 if (priv->n_read >= HEADER_SIZE)
793 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
798 GError *read_error = NULL;
800 status = g_io_channel_read_chars (priv->from_server_channel,
801 (gchar *) priv->read_buffer + priv->n_read,
802 n_to_read - priv->n_read,
805 if (status == G_IO_STATUS_AGAIN)
810 else if (status != G_IO_STATUS_NORMAL)
812 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
813 "Failed to read from daemon: %s",
814 read_error->message);
815 g_clear_error (&read_error);
819 g_debug ("Read %zi bytes from daemon", n_read);
821 priv->n_read += n_read;
822 } while (priv->n_read < n_to_read && block);
824 /* Stop if haven't got all the data we want */
825 if (priv->n_read != n_to_read)
834 /* If have header, rerun for content */
835 if (priv->n_read == HEADER_SIZE)
837 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
840 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
841 return recv_message (greeter, block, message, length, error);
846 *message = priv->read_buffer;
848 g_free (priv->read_buffer);
850 *length = priv->n_read;
852 priv->read_buffer = g_malloc (priv->n_read);
859 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
861 LightDMGreeter *greeter = data;
863 gsize message_length;
864 GError *error = NULL;
866 /* Read one message and process it */
867 if (!recv_message (greeter, FALSE, &message, &message_length, &error))
869 // FIXME: Should push this up to the client somehow
870 g_warning ("Failed to read from daemon: %s\n", error->message);
871 g_clear_error (&error);
872 return G_SOURCE_REMOVE;
877 handle_message (greeter, message, message_length);
881 return G_SOURCE_CONTINUE;
885 send_connect (LightDMGreeter *greeter, gboolean resettable, GError **error)
887 guint8 message[MAX_MESSAGE_LENGTH];
890 g_debug ("Connecting to display manager...");
891 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset, error) &&
892 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset, error) &&
893 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset, error) &&
894 send_message (greeter, message, offset, error);
898 send_start_session (LightDMGreeter *greeter, const gchar *session, GError **error)
900 guint8 message[MAX_MESSAGE_LENGTH];
904 g_debug ("Starting session %s", session);
906 g_debug ("Starting default session");
908 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset, error) &&
909 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
910 send_message (greeter, message, offset, error);
914 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GError **error)
916 guint8 message[MAX_MESSAGE_LENGTH];
919 g_debug ("Ensuring data directory for user %s", username);
921 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset, error) &&
922 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
923 send_message (greeter, message, offset, error);
927 * lightdm_greeter_connect_to_daemon:
928 * @greeter: The greeter to connect
929 * @cancellable: (allow-none): A #GCancellable or %NULL.
930 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
931 * @user_data: (allow-none): data to pass to the @callback or %NULL.
933 * Asynchronously connects the greeter to the display manager.
935 * 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.
937 * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
940 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
942 LightDMGreeterPrivate *priv;
944 GError *error = NULL;
946 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
948 priv = lightdm_greeter_get_instance_private (greeter);
950 request = request_new (greeter, cancellable, callback, user_data);
951 if (send_connect (greeter, priv->resettable, &error))
952 priv->connect_requests = g_list_append (priv->connect_requests, request);
955 request->error = error;
956 request_complete (request);
957 g_object_unref (request);
962 * lightdm_greeter_connect_to_daemon_finish:
963 * @greeter: The greeter the the request was done with
964 * @result: A #GAsyncResult.
965 * @error: return location for a #GError, or %NULL
967 * Finishes an operation started with lightdm_greeter_connect_to_daemon().
969 * Return value: #TRUE if successfully connected
972 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
974 Request *request = REQUEST (result);
976 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
979 g_propagate_error (error, request->error);
980 return request->result;
984 * lightdm_greeter_connect_to_daemon_sync:
985 * @greeter: The greeter to connect
986 * @error: return location for a #GError, or %NULL
988 * Connects the greeter to the display manager. Will block until connected.
990 * Return value: #TRUE if successfully connected
993 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
995 LightDMGreeterPrivate *priv;
998 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1000 priv = lightdm_greeter_get_instance_private (greeter);
1002 /* Read until we are connected */
1003 if (!send_connect (greeter, priv->resettable, error))
1005 request = request_new (greeter, NULL, NULL, NULL);
1006 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
1010 gsize message_length;
1012 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1014 handle_message (greeter, message, message_length);
1016 } while (!request->complete);
1018 return lightdm_greeter_connect_to_daemon_finish (greeter, G_ASYNC_RESULT (request), error);
1022 * lightdm_greeter_connect_sync:
1023 * @greeter: The greeter to connect
1024 * @error: return location for a #GError, or %NULL
1026 * Connects the greeter to the display manager. Will block until connected.
1028 * Return value: #TRUE if successfully connected
1030 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
1033 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
1035 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
1039 * lightdm_greeter_get_hint:
1040 * @greeter: A #LightDMGreeter
1041 * @name: The hint name to query.
1045 * Return value: (nullable): The value for this hint or #NULL if not set.
1048 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
1050 LightDMGreeterPrivate *priv;
1052 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1054 priv = lightdm_greeter_get_instance_private (greeter);
1056 return g_hash_table_lookup (priv->hints, name);
1060 * lightdm_greeter_get_default_session_hint:
1061 * @greeter: A #LightDMGreeter
1063 * Get the default session to use.
1065 * Return value: The session name
1068 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
1070 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1071 return lightdm_greeter_get_hint (greeter, "default-session");
1075 * lightdm_greeter_get_hide_users_hint:
1076 * @greeter: A #LightDMGreeter
1078 * Check if user accounts should be shown. If this is TRUE then the list of
1079 * accounts should be taken from #LightDMUserList and displayed in the greeter
1080 * for the user to choose from. Note that this list can be empty and it is
1081 * recommended you show a method for the user to enter a username manually.
1083 * If this option is shown the greeter should only allow these users to be
1084 * chosen for login unless the manual login hint is set.
1086 * Return value: #TRUE if the available users should not be shown.
1089 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
1093 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1094 value = lightdm_greeter_get_hint (greeter, "hide-users");
1096 return g_strcmp0 (value, "true") == 0;
1100 * lightdm_greeter_get_show_manual_login_hint:
1101 * @greeter: A #LightDMGreeter
1103 * Check if a manual login option should be shown. If set the GUI
1104 * should provide a way for a username to be entered manually.
1105 * Without this hint a greeter which is showing a user list can
1106 * limit logins to only those users.
1108 * Return value: #TRUE if a manual login option should be shown.
1111 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
1115 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1116 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
1118 return g_strcmp0 (value, "true") == 0;
1122 * lightdm_greeter_get_show_remote_login_hint:
1123 * @greeter: A #LightDMGreeter
1125 * Check if a remote login option should be shown. If set the GUI
1126 * should provide a way for a user to log into a remote desktop server.
1128 * Return value: #TRUE if a remote login option should be shown.
1131 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
1135 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1136 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
1138 return g_strcmp0 (value, "true") == 0;
1142 * lightdm_greeter_get_lock_hint:
1143 * @greeter: A #LightDMGreeter
1145 * Check if the greeter is acting as a lock screen.
1147 * Return value: #TRUE if the greeter was triggered by locking the seat.
1150 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
1154 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1155 value = lightdm_greeter_get_hint (greeter, "lock-screen");
1157 return g_strcmp0 (value, "true") == 0;
1161 * lightdm_greeter_get_has_guest_account_hint:
1162 * @greeter: A #LightDMGreeter
1164 * Check if guest sessions are supported.
1166 * Return value: #TRUE if guest sessions are supported.
1169 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
1173 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1174 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
1176 return g_strcmp0 (value, "true") == 0;
1180 * lightdm_greeter_get_select_user_hint:
1181 * @greeter: A #LightDMGreeter
1183 * Get the user to select by default.
1185 * Return value: (nullable): A username or %NULL if no particular user should be selected.
1188 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
1190 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1191 return lightdm_greeter_get_hint (greeter, "select-user");
1195 * lightdm_greeter_get_select_guest_hint:
1196 * @greeter: A #LightDMGreeter
1198 * Check if the guest account should be selected by default.
1200 * Return value: #TRUE if the guest account should be selected by default.
1203 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1207 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1208 value = lightdm_greeter_get_hint (greeter, "select-guest");
1210 return g_strcmp0 (value, "true") == 0;
1214 * lightdm_greeter_get_autologin_user_hint:
1215 * @greeter: A #LightDMGreeter
1217 * Get the user account to automatically log into when the timer expires.
1219 * Return value: (nullable): The user account to automatically log into or %NULL if none configured.
1222 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1224 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1225 return lightdm_greeter_get_hint (greeter, "autologin-user");
1229 * lightdm_greeter_get_autologin_guest_hint:
1230 * @greeter: A #LightDMGreeter
1232 * Check if the guest account should be automatically logged into when the timer expires.
1234 * Return value: #TRUE if the guest account should be automatically logged into.
1237 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1241 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1242 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1244 return g_strcmp0 (value, "true") == 0;
1248 * lightdm_greeter_get_autologin_timeout_hint:
1249 * @greeter: A #LightDMGreeter
1251 * Get the number of seconds to wait before automaitcally logging in.
1253 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1256 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1261 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1262 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1264 timeout = atoi (value);
1272 * lightdm_greeter_cancel_autologin:
1273 * @greeter: A #LightDMGreeter
1275 * Cancel the automatic login.
1278 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1280 LightDMGreeterPrivate *priv;
1282 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1284 priv = lightdm_greeter_get_instance_private (greeter);
1286 if (priv->autologin_timeout)
1287 g_source_remove (priv->autologin_timeout);
1288 priv->autologin_timeout = 0;
1292 * lightdm_greeter_authenticate:
1293 * @greeter: A #LightDMGreeter
1294 * @username: (allow-none): A username or #NULL to prompt for a username.
1295 * @error: return location for a #GError, or %NULL
1297 * Starts the authentication procedure for a user.
1299 * Return value: #TRUE if authentication request sent.
1302 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username, GError **error)
1304 LightDMGreeterPrivate *priv;
1305 guint8 message[MAX_MESSAGE_LENGTH];
1308 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1310 priv = lightdm_greeter_get_instance_private (greeter);
1312 g_return_val_if_fail (priv->connected, FALSE);
1314 priv->cancelling_authentication = FALSE;
1315 priv->authenticate_sequence_number++;
1316 priv->in_authentication = TRUE;
1317 priv->is_authenticated = FALSE;
1318 if (username != priv->authentication_user)
1320 g_free (priv->authentication_user);
1321 priv->authentication_user = g_strdup (username);
1324 g_debug ("Starting authentication for user %s...", username);
1325 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset, error) &&
1326 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1327 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1328 send_message (greeter, message, offset, error);
1332 * lightdm_greeter_authenticate_as_guest:
1333 * @greeter: A #LightDMGreeter
1334 * @error: return location for a #GError, or %NULL
1336 * Starts the authentication procedure for the guest user.
1338 * Return value: #TRUE if authentication request sent.
1341 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter, GError **error)
1343 LightDMGreeterPrivate *priv;
1344 guint8 message[MAX_MESSAGE_LENGTH];
1347 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1349 priv = lightdm_greeter_get_instance_private (greeter);
1351 g_return_val_if_fail (priv->connected, FALSE);
1353 priv->cancelling_authentication = FALSE;
1354 priv->authenticate_sequence_number++;
1355 priv->in_authentication = TRUE;
1356 priv->is_authenticated = FALSE;
1357 g_free (priv->authentication_user);
1358 priv->authentication_user = NULL;
1360 g_debug ("Starting authentication for guest account...");
1361 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset, error) &&
1362 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1363 send_message (greeter, message, offset, error);
1367 * lightdm_greeter_authenticate_autologin:
1368 * @greeter: A #LightDMGreeter
1369 * @error: return location for a #GError, or %NULL
1371 * Starts the authentication procedure for the automatic login user.
1373 * Return value: #TRUE if authentication request sent.
1376 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter, GError **error)
1380 user = lightdm_greeter_get_autologin_user_hint (greeter);
1381 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1382 return lightdm_greeter_authenticate_as_guest (greeter, error);
1384 return lightdm_greeter_authenticate (greeter, user, error);
1387 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN,
1388 "Can't authenticate autologin; autologin not configured");
1394 * lightdm_greeter_authenticate_remote:
1395 * @greeter: A #LightDMGreeter
1396 * @session: The name of a remote session
1397 * @username: (allow-none): A username of #NULL to prompt for a username.
1398 * @error: return location for a #GError, or %NULL
1400 * Start authentication for a remote session type.
1402 * Return value: #TRUE if authentication request sent.
1405 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username, GError **error)
1407 LightDMGreeterPrivate *priv;
1408 guint8 message[MAX_MESSAGE_LENGTH];
1411 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1413 priv = lightdm_greeter_get_instance_private (greeter);
1415 g_return_val_if_fail (priv->connected, FALSE);
1417 priv->cancelling_authentication = FALSE;
1418 priv->authenticate_sequence_number++;
1419 priv->in_authentication = TRUE;
1420 priv->is_authenticated = FALSE;
1421 g_free (priv->authentication_user);
1422 priv->authentication_user = NULL;
1425 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1427 g_debug ("Starting authentication for remote session %s...", session);
1429 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset, error) &&
1430 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1431 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
1432 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1433 send_message (greeter, message, offset, error);
1437 * lightdm_greeter_respond:
1438 * @greeter: A #LightDMGreeter
1439 * @response: Response to a prompt
1440 * @error: return location for a #GError, or %NULL
1442 * Provide response to a prompt. May be one in a series.
1444 * Return value: #TRUE if response sent.
1447 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response, GError **error)
1449 LightDMGreeterPrivate *priv;
1450 guint8 message[MAX_MESSAGE_LENGTH];
1453 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1454 g_return_val_if_fail (response != NULL, FALSE);
1456 priv = lightdm_greeter_get_instance_private (greeter);
1458 g_return_val_if_fail (priv->connected, FALSE);
1459 g_return_val_if_fail (priv->n_responses_waiting > 0, FALSE);
1461 priv->n_responses_waiting--;
1462 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1464 if (priv->n_responses_waiting == 0)
1469 g_debug ("Providing response to display manager");
1471 msg_length = int_length ();
1472 for (iter = priv->responses_received; iter; iter = iter->next)
1473 msg_length += string_length ((gchar *)iter->data);
1475 if (!write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset, error) ||
1476 !write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset, error))
1478 for (iter = priv->responses_received; iter; iter = iter->next)
1480 if (!write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset, error))
1483 if (!send_message (greeter, message, offset, error))
1486 g_list_free_full (priv->responses_received, g_free);
1487 priv->responses_received = NULL;
1494 * lightdm_greeter_cancel_authentication:
1495 * @greeter: A #LightDMGreeter
1496 * @error: return location for a #GError, or %NULL
1498 * Cancel the current user authentication.
1500 * Return value: #TRUE if cancel request sent.
1503 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter, GError **error)
1505 LightDMGreeterPrivate *priv;
1506 guint8 message[MAX_MESSAGE_LENGTH];
1509 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1511 priv = lightdm_greeter_get_instance_private (greeter);
1513 g_return_val_if_fail (priv->connected, FALSE);
1515 priv->cancelling_authentication = TRUE;
1516 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset, error) &&
1517 send_message (greeter, message, offset, error);
1521 * lightdm_greeter_get_in_authentication:
1522 * @greeter: A #LightDMGreeter
1524 * Checks if the greeter is in the process of authenticating.
1526 * Return value: #TRUE if the greeter is authenticating a user.
1529 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1531 LightDMGreeterPrivate *priv;
1533 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1535 priv = lightdm_greeter_get_instance_private (greeter);
1537 return priv->in_authentication;
1541 * lightdm_greeter_get_is_authenticated:
1542 * @greeter: A #LightDMGreeter
1544 * Checks if the greeter has successfully authenticated.
1546 * Return value: #TRUE if the greeter is authenticated for login.
1549 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1551 LightDMGreeterPrivate *priv;
1553 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1555 priv = lightdm_greeter_get_instance_private (greeter);
1557 return priv->is_authenticated;
1561 * lightdm_greeter_get_authentication_user:
1562 * @greeter: A #LightDMGreeter
1564 * Get the user that is being authenticated.
1566 * Return value: (nullable): The username of the authentication user being authenticated or #NULL if no authentication in progress.
1569 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1571 LightDMGreeterPrivate *priv;
1573 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1575 priv = lightdm_greeter_get_instance_private (greeter);
1577 return priv->authentication_user;
1581 * lightdm_greeter_set_language:
1582 * @greeter: A #LightDMGreeter
1583 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1584 * @error: return location for a #GError, or %NULL
1586 * Set the language for the currently authenticated user.
1588 * Return value: #TRUE if set language request sent.
1591 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language, GError **error)
1593 LightDMGreeterPrivate *priv;
1594 guint8 message[MAX_MESSAGE_LENGTH];
1597 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1599 priv = lightdm_greeter_get_instance_private (greeter);
1601 g_return_val_if_fail (priv->connected, FALSE);
1603 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset, error) &&
1604 write_string (message, MAX_MESSAGE_LENGTH, language, &offset, error) &&
1605 send_message (greeter, message, offset, error);
1609 * lightdm_greeter_start_session:
1610 * @greeter: A #LightDMGreeter
1611 * @session: (allow-none): The session to log into or #NULL to use the default.
1612 * @cancellable: (allow-none): A #GCancellable or %NULL.
1613 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1614 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1616 * Asynchronously start a session for the authenticated user.
1618 * 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.
1620 * See lightdm_greeter_start_session_sync() for the synchronous version.
1623 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1625 LightDMGreeterPrivate *priv;
1627 GError *error = NULL;
1629 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1631 priv = lightdm_greeter_get_instance_private (greeter);
1633 request = request_new (greeter, cancellable, callback, user_data);
1634 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1635 if (!send_start_session (greeter, session, &error))
1637 request->error = error;
1638 request_complete (request);
1643 * lightdm_greeter_start_session_finish:
1644 * @greeter: A #LightDMGreeter
1645 * @result: A #GAsyncResult.
1646 * @error: return location for a #GError, or %NULL
1648 * Start a session for the authenticated user.
1650 * Return value: TRUE if the session was started.
1653 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1655 Request *request = REQUEST (result);
1657 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1660 g_propagate_error (error, request->error);
1661 return request->result;
1665 * lightdm_greeter_start_session_sync:
1666 * @greeter: A #LightDMGreeter
1667 * @session: (allow-none): The session to log into or #NULL to use the default.
1668 * @error: return location for a #GError, or %NULL
1670 * Start a session for the authenticated user.
1672 * Return value: TRUE if the session was started.
1675 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1677 LightDMGreeterPrivate *priv;
1680 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1682 priv = lightdm_greeter_get_instance_private (greeter);
1684 g_return_val_if_fail (priv->connected, FALSE);
1685 g_return_val_if_fail (priv->is_authenticated, FALSE);
1687 /* Read until the session is started */
1688 if (!send_start_session (greeter, session, error))
1690 request = request_new (greeter, NULL, NULL, NULL);
1691 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1695 gsize message_length;
1697 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1699 handle_message (greeter, message, message_length);
1701 } while (!request->complete);
1703 return lightdm_greeter_start_session_finish (greeter, G_ASYNC_RESULT (request), error);
1707 * lightdm_greeter_ensure_shared_data_dir:
1708 * @greeter: A #LightDMGreeter
1709 * @username: A username
1710 * @cancellable: (allow-none): A #GCancellable or %NULL.
1711 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1712 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1714 * Ensure that a shared data dir for the given user is available. Both the
1715 * greeter user and @username will have write access to that folder. The
1716 * intention is that larger pieces of shared data would be stored there (files
1717 * that the greeter creates but wants to give to a user -- like camera
1718 * photos -- or files that the user creates but wants the greeter to
1719 * see -- like contact avatars).
1721 * LightDM will automatically create these if the user actually logs in, so
1722 * greeters only need to call this method if they want to store something in
1723 * the directory themselves.
1726 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1728 LightDMGreeterPrivate *priv;
1730 GError *error = NULL;
1732 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1734 priv = lightdm_greeter_get_instance_private (greeter);
1736 request = request_new (greeter, cancellable, callback, user_data);
1737 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1738 if (!send_ensure_shared_data_dir (greeter, username, &error))
1740 request->error = error;
1741 request_complete (request);
1746 * lightdm_greeter_ensure_shared_data_dir_finish:
1747 * @result: A #GAsyncResult.
1748 * @greeter: A #LightDMGreeter
1749 * @error: return location for a #GError, or %NULL
1751 * Function to call from lightdm_greeter_ensure_shared_data_dir callback.
1753 * Return value: The path to the shared directory, free with g_free.
1756 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1758 Request *request = REQUEST (result);
1760 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1763 g_propagate_error (error, request->error);
1764 return g_strdup (request->dir);
1768 * lightdm_greeter_ensure_shared_data_dir_sync:
1769 * @greeter: A #LightDMGreeter
1770 * @username: A username
1771 * @error: return location for a #GError, or %NULL
1773 * Ensure that a shared data dir for the given user is available. Both the
1774 * greeter user and @username will have write access to that folder. The
1775 * intention is that larger pieces of shared data would be stored there (files
1776 * that the greeter creates but wants to give to a user -- like camera
1777 * photos -- or files that the user creates but wants the greeter to
1778 * see -- like contact avatars).
1780 * LightDM will automatically create these if the user actually logs in, so
1781 * greeters only need to call this method if they want to store something in
1782 * the directory themselves.
1784 * Return value: The path to the shared directory, free with g_free.
1787 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username, GError **error)
1789 LightDMGreeterPrivate *priv;
1792 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1794 priv = lightdm_greeter_get_instance_private (greeter);
1796 g_return_val_if_fail (priv->connected, NULL);
1798 /* Read until a response */
1799 if (!send_ensure_shared_data_dir (greeter, username, error))
1801 request = request_new (greeter, NULL, NULL, NULL);
1802 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1806 gsize message_length;
1808 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1810 handle_message (greeter, message, message_length);
1812 } while (!request->complete);
1814 return lightdm_greeter_ensure_shared_data_dir_finish (greeter, G_ASYNC_RESULT (request), error);
1818 lightdm_greeter_init (LightDMGreeter *greeter)
1820 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (greeter);
1822 priv->read_buffer = g_malloc (HEADER_SIZE);
1823 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1827 lightdm_greeter_set_property (GObject *object,
1829 const GValue *value,
1832 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1836 lightdm_greeter_get_property (GObject *object,
1841 LightDMGreeter *self;
1843 self = LIGHTDM_GREETER (object);
1846 case PROP_DEFAULT_SESSION_HINT:
1847 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1849 case PROP_HIDE_USERS_HINT:
1850 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1852 case PROP_SHOW_MANUAL_LOGIN_HINT:
1853 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1855 case PROP_SHOW_REMOTE_LOGIN_HINT:
1856 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1858 case PROP_LOCK_HINT:
1859 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1861 case PROP_HAS_GUEST_ACCOUNT_HINT:
1862 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1864 case PROP_SELECT_USER_HINT:
1865 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1867 case PROP_SELECT_GUEST_HINT:
1868 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1870 case PROP_AUTOLOGIN_USER_HINT:
1871 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1873 case PROP_AUTOLOGIN_GUEST_HINT:
1874 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1876 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1877 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1879 case PROP_AUTHENTICATION_USER:
1880 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1882 case PROP_IN_AUTHENTICATION:
1883 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1885 case PROP_IS_AUTHENTICATED:
1886 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1889 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1895 lightdm_greeter_finalize (GObject *object)
1897 LightDMGreeter *self = LIGHTDM_GREETER (object);
1898 LightDMGreeterPrivate *priv = lightdm_greeter_get_instance_private (self);
1900 g_clear_object (&priv->socket);
1901 if (priv->to_server_channel)
1902 g_io_channel_unref (priv->to_server_channel);
1903 if (priv->from_server_channel)
1904 g_io_channel_unref (priv->from_server_channel);
1905 if (priv->from_server_watch)
1906 g_source_remove (priv->from_server_watch);
1907 priv->from_server_watch = 0;
1908 g_clear_pointer (&priv->read_buffer, g_free);
1909 g_list_free_full (priv->responses_received, g_free);
1910 priv->responses_received = NULL;
1911 g_list_free_full (priv->connect_requests, g_object_unref);
1912 priv->connect_requests = NULL;
1913 g_list_free_full (priv->start_session_requests, g_object_unref);
1914 priv->start_session_requests = NULL;
1915 g_list_free_full (priv->ensure_shared_data_dir_requests, g_object_unref);
1916 priv->ensure_shared_data_dir_requests = NULL;
1917 g_clear_pointer (&priv->authentication_user, g_free);
1918 g_hash_table_unref (priv->hints);
1921 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1925 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1927 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1929 object_class->set_property = lightdm_greeter_set_property;
1930 object_class->get_property = lightdm_greeter_get_property;
1931 object_class->finalize = lightdm_greeter_finalize;
1933 g_object_class_install_property (object_class,
1934 PROP_DEFAULT_SESSION_HINT,
1935 g_param_spec_string ("default-session-hint",
1936 "default-session-hint",
1937 "Default session hint",
1941 g_object_class_install_property (object_class,
1942 PROP_HIDE_USERS_HINT,
1943 g_param_spec_boolean ("hide-users-hint",
1949 g_object_class_install_property (object_class,
1950 PROP_SHOW_MANUAL_LOGIN_HINT,
1951 g_param_spec_boolean ("show-manual-login-hint",
1952 "show-manual-login-hint",
1953 "Show manual login hint",
1957 g_object_class_install_property (object_class,
1958 PROP_SHOW_REMOTE_LOGIN_HINT,
1959 g_param_spec_boolean ("show-remote-login-hint",
1960 "show-remote-login-hint",
1961 "Show remote login hint",
1965 g_object_class_install_property (object_class,
1967 g_param_spec_boolean ("lock-hint",
1973 g_object_class_install_property (object_class,
1974 PROP_HAS_GUEST_ACCOUNT_HINT,
1975 g_param_spec_boolean ("has-guest-account-hint",
1976 "has-guest-account-hint",
1977 "Has guest account hint",
1981 g_object_class_install_property (object_class,
1982 PROP_SELECT_USER_HINT,
1983 g_param_spec_string ("select-user-hint",
1989 g_object_class_install_property (object_class,
1990 PROP_SELECT_GUEST_HINT,
1991 g_param_spec_boolean ("select-guest-hint",
1992 "select-guest-hint",
1993 "Select guest account hint",
1997 g_object_class_install_property (object_class,
1998 PROP_AUTOLOGIN_USER_HINT,
1999 g_param_spec_string ("autologin-user-hint",
2000 "autologin-user-hint",
2001 "Autologin user hint",
2005 g_object_class_install_property (object_class,
2006 PROP_AUTOLOGIN_GUEST_HINT,
2007 g_param_spec_boolean ("autologin-guest-hint",
2008 "autologin-guest-hint",
2009 "Autologin guest account hint",
2013 g_object_class_install_property (object_class,
2014 PROP_AUTOLOGIN_TIMEOUT_HINT,
2015 g_param_spec_int ("autologin-timeout-hint",
2016 "autologin-timeout-hint",
2017 "Autologin timeout hint",
2021 g_object_class_install_property (object_class,
2022 PROP_AUTHENTICATION_USER,
2023 g_param_spec_string ("authentication-user",
2024 "authentication-user",
2025 "The user being authenticated",
2028 g_object_class_install_property (object_class,
2029 PROP_IN_AUTHENTICATION,
2030 g_param_spec_boolean ("in-authentication",
2031 "in-authentication",
2032 "TRUE if a user is being authenticated",
2035 g_object_class_install_property (object_class,
2036 PROP_IS_AUTHENTICATED,
2037 g_param_spec_boolean ("is-authenticated",
2039 "TRUE if the selected user is authenticated",
2044 * LightDMGreeter::show-prompt:
2045 * @greeter: A #LightDMGreeter
2046 * @text: Prompt text
2047 * @type: Prompt type
2049 * The ::show-prompt signal gets emitted when the greeter should show a
2050 * prompt to the user. The given text should be displayed and an input
2051 * field for the user to provide a response.
2053 * Call lightdm_greeter_respond() with the resultant input or
2054 * lightdm_greeter_cancel_authentication() to abort the authentication.
2056 signals[SHOW_PROMPT] =
2057 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
2058 G_TYPE_FROM_CLASS (klass),
2060 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
2063 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_prompt_type_get_type ());
2066 * LightDMGreeter::show-message:
2067 * @greeter: A #LightDMGreeter
2068 * @text: Message text
2069 * @type: Message type
2071 * The ::show-message signal gets emitted when the greeter
2072 * should show a message to the user.
2074 signals[SHOW_MESSAGE] =
2075 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
2076 G_TYPE_FROM_CLASS (klass),
2078 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
2081 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_message_type_get_type ());
2084 * LightDMGreeter::authentication-complete:
2085 * @greeter: A #LightDMGreeter
2087 * The ::authentication-complete signal gets emitted when the greeter
2088 * has completed authentication.
2090 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
2093 signals[AUTHENTICATION_COMPLETE] =
2094 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
2095 G_TYPE_FROM_CLASS (klass),
2097 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
2103 * LightDMGreeter::autologin-timer-expired:
2104 * @greeter: A #LightDMGreeter
2106 * The ::timed-login signal gets emitted when the automatic login timer has expired.
2107 * The application should then call lightdm_greeter_login().
2109 signals[AUTOLOGIN_TIMER_EXPIRED] =
2110 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
2111 G_TYPE_FROM_CLASS (klass),
2113 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
2119 * LightDMGreeter::idle:
2120 * @greeter: A #LightDMGreeter
2122 * The ::idle signal gets emitted when the user has logged in and the
2123 * greeter is no longer needed.
2125 * This signal only matters if the greeter has marked itself as
2126 * resettable using lightdm_greeter_set_resettable().
2129 g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
2130 G_TYPE_FROM_CLASS (klass),
2132 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
2138 * LightDMGreeter::reset:
2139 * @greeter: A #LightDMGreeter
2141 * The ::reset signal gets emitted when the user is returning to a greeter
2142 * that was previously marked idle.
2144 * This signal only matters if the greeter has marked itself as
2145 * resettable using lightdm_greeter_set_resettable().
2148 g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
2149 G_TYPE_FROM_CLASS (klass),
2151 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
2158 request_init (Request *request)
2163 request_finalize (GObject *object)
2165 Request *request = REQUEST (object);
2167 g_clear_object (&request->cancellable);
2168 g_free (request->dir);
2170 G_OBJECT_CLASS (request_parent_class)->finalize (object);
2174 request_class_init (RequestClass *klass)
2176 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2177 object_class->finalize = request_finalize;
2181 request_get_user_data (GAsyncResult *result)
2183 return REQUEST (result)->user_data;
2187 request_get_source_object (GAsyncResult *result)
2189 return g_object_ref (REQUEST (result)->greeter);
2193 request_iface_init (GAsyncResultIface *iface)
2195 iface->get_user_data = request_get_user_data;
2196 iface->get_source_object = request_get_source_object;