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.
15 #include <security/pam_appl.h>
17 #include "lightdm/greeter.h"
19 G_DEFINE_QUARK (lightdm_greeter_error, lightdm_greeter_error)
23 PROP_DEFAULT_SESSION_HINT,
25 PROP_SHOW_MANUAL_LOGIN_HINT,
26 PROP_SHOW_REMOTE_LOGIN_HINT,
28 PROP_HAS_GUEST_ACCOUNT_HINT,
29 PROP_SELECT_USER_HINT,
30 PROP_SELECT_GUEST_HINT,
31 PROP_AUTOLOGIN_USER_HINT,
32 PROP_AUTOLOGIN_GUEST_HINT,
33 PROP_AUTOLOGIN_TIMEOUT_HINT,
34 PROP_AUTHENTICATION_USER,
35 PROP_IN_AUTHENTICATION,
36 PROP_IS_AUTHENTICATED,
42 AUTHENTICATION_COMPLETE,
43 AUTOLOGIN_TIMER_EXPIRED,
48 static guint signals[LAST_SIGNAL] = { 0 };
52 /* TRUE if the daemon can reuse this greeter */
55 /* Channel to write to daemon */
56 GIOChannel *to_server_channel;
58 /* Channel to read from daemon */
59 GIOChannel *from_server_channel;
61 /* Data read from the daemon */
65 gsize n_responses_waiting;
66 GList *responses_received;
68 /* TRUE if have got a connect response */
71 /* Pending connect requests */
72 GList *connect_requests;
74 /* Pending start session requests */
75 GList *start_session_requests;
77 /* Pending ensure shared data dir requests */
78 GList *ensure_shared_data_dir_requests;
80 /* Hints provided by the daemon */
83 /* Timeout source to notify greeter to autologin */
84 guint autologin_timeout;
86 gchar *authentication_user;
87 gboolean in_authentication;
88 gboolean is_authenticated;
89 guint32 authenticate_sequence_number;
90 gboolean cancelling_authentication;
91 } LightDMGreeterPrivate;
93 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
95 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
98 #define MAX_MESSAGE_LENGTH 1024
100 /* Messages from the greeter to the server */
103 GREETER_MESSAGE_CONNECT = 0,
104 GREETER_MESSAGE_AUTHENTICATE,
105 GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
106 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
107 GREETER_MESSAGE_START_SESSION,
108 GREETER_MESSAGE_CANCEL_AUTHENTICATION,
109 GREETER_MESSAGE_SET_LANGUAGE,
110 GREETER_MESSAGE_AUTHENTICATE_REMOTE,
111 GREETER_MESSAGE_ENSURE_SHARED_DIR,
114 /* Messages from the server to the greeter */
117 SERVER_MESSAGE_CONNECTED = 0,
118 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
119 SERVER_MESSAGE_END_AUTHENTICATION,
120 SERVER_MESSAGE_SESSION_RESULT,
121 SERVER_MESSAGE_SHARED_DIR_RESULT,
123 SERVER_MESSAGE_RESET,
126 /* Request sent to server */
129 GObject parent_instance;
130 LightDMGreeter *greeter;
131 GCancellable *cancellable;
132 GAsyncReadyCallback callback;
141 GObjectClass parent_class;
143 GType request_get_type (void);
144 static void request_iface_init (GAsyncResultIface *iface);
145 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
146 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
148 static gboolean from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data);
151 lightdm_greeter_error_get_type (void)
153 static GType enum_type = 0;
155 if (G_UNLIKELY(enum_type == 0)) {
156 static const GEnumValue values[] = {
157 { LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR, "LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR", "communication-error" },
158 { LIGHTDM_GREETER_ERROR_CONNECTION_FAILED, "LIGHTDM_GREETER_ERROR_CONNECTION_FAILED", "connection-failed" },
159 { LIGHTDM_GREETER_ERROR_SESSION_FAILED, "LIGHTDM_GREETER_ERROR_SESSION_FAILED", "session-failed" },
160 { LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN, "LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN", "no-autologin" },
161 { LIGHTDM_GREETER_ERROR_INVALID_USER, "LIGHTDM_GREETER_ERROR_INVALID_USER", "invalid-user" },
164 enum_type = g_enum_register_static (g_intern_static_string ("LightDMGreeterError"), values);
171 lightdm_prompt_type_get_type (void)
173 static GType enum_type = 0;
175 if (G_UNLIKELY(enum_type == 0)) {
176 static const GEnumValue values[] = {
177 { LIGHTDM_PROMPT_TYPE_QUESTION, "LIGHTDM_PROMPT_TYPE_QUESTION", "question" },
178 { LIGHTDM_PROMPT_TYPE_SECRET, "LIGHTDM_PROMPT_TYPE_SECRET", "secret" },
181 enum_type = g_enum_register_static (g_intern_static_string ("LightDMPromptType"), values);
188 lightdm_message_type_get_type (void)
190 static GType enum_type = 0;
192 if (G_UNLIKELY(enum_type == 0)) {
193 static const GEnumValue values[] = {
194 { LIGHTDM_MESSAGE_TYPE_INFO, "LIGHTDM_MESSAGE_TYPE_INFO", "info" },
195 { LIGHTDM_MESSAGE_TYPE_ERROR, "LIGHTDM_MESSAGE_TYPE_ERROR", "error" },
198 enum_type = g_enum_register_static (g_intern_static_string ("LightDMMessageType"), values);
206 * lightdm_greeter_new:
208 * Create a new greeter.
210 * Return value: the new #LightDMGreeter
213 lightdm_greeter_new (void)
215 return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
219 * lightdm_greeter_set_resettable:
220 * @greeter: A #LightDMGreeter
221 * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
223 * Set whether the greeter will be reset instead of killed after the user logs in.
224 * This must be called before lightdm_greeter_connect is called.
227 lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
229 LightDMGreeterPrivate *priv;
231 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
233 priv = GET_PRIVATE (greeter);
235 g_return_if_fail (!priv->connected);
236 priv->resettable = resettable;
240 request_new (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
244 request = g_object_new (request_get_type (), NULL);
245 request->greeter = g_object_ref (greeter);
247 request->cancellable = g_object_ref (cancellable);
248 request->callback = callback;
249 request->user_data = user_data;
255 request_callback_cb (gpointer data)
257 Request *request = data;
258 if (request->callback)
259 request->callback (G_OBJECT (request->greeter), G_ASYNC_RESULT (request), request->user_data);
260 g_object_unref (request);
261 return G_SOURCE_REMOVE;
265 request_complete (Request *request)
267 request->complete = TRUE;
269 if (!request->callback)
272 if (request->cancellable && g_cancellable_is_cancelled (request->cancellable))
275 g_idle_add (request_callback_cb, g_object_ref (request));
279 timed_login_cb (gpointer data)
281 LightDMGreeter *greeter = data;
282 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
284 priv->autologin_timeout = 0;
285 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
297 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset, GError **error)
299 if (*offset + 4 >= buffer_length)
301 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
302 "Not enough buffer space to write integer");
305 buffer[*offset] = value >> 24;
306 buffer[*offset+1] = (value >> 16) & 0xFF;
307 buffer[*offset+2] = (value >> 8) & 0xFF;
308 buffer[*offset+3] = value & 0xFF;
315 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset, GError **error)
320 length = strlen (value);
321 if (!write_int (buffer, buffer_length, length, offset, error))
323 if (*offset + length >= buffer_length)
325 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
326 "Not enough buffer space to write string of length %d octets", length);
330 memcpy (buffer + *offset, value, length);
337 read_int (guint8 *message, gsize message_length, gsize *offset)
342 if (message_length - *offset < int_length ())
344 g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
348 buffer = message + *offset;
349 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
350 *offset += int_length ();
356 read_string (guint8 *message, gsize message_length, gsize *offset)
361 length = read_int (message, message_length, offset);
362 if (message_length - *offset < length)
364 g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
365 return g_strdup ("");
368 value = g_malloc (sizeof (gchar) * (length + 1));
369 memcpy (value, message + *offset, length);
370 value[length] = '\0';
377 string_length (const gchar *value)
380 return int_length () + strlen (value);
382 return int_length ();
386 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset, GError **error)
388 return write_int (buffer, buffer_length, id, offset, error) &&
389 write_int (buffer, buffer_length, length, offset, error);
393 get_message_length (guint8 *message, gsize message_length)
396 return read_int (message, message_length, &offset);
400 connect_to_daemon (LightDMGreeter *greeter, GError **error)
402 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
403 const gchar *to_server_fd, *from_server_fd;
405 if (priv->to_server_channel || priv->from_server_channel)
408 to_server_fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
409 from_server_fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
410 if (!to_server_fd || !from_server_fd)
412 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_CONNECTION_FAILED,
413 "Unable to determine socket to daemon");
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));
419 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
421 if (!g_io_channel_set_encoding (priv->to_server_channel, NULL, error) ||
422 !g_io_channel_set_encoding (priv->from_server_channel, NULL, error))
429 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length, GError **error)
431 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
434 guint32 stated_length;
435 GError *flush_error = NULL;
437 if (!connect_to_daemon (greeter, error))
440 /* Double check that we're sending well-formed messages. If we say we're
441 sending more than we do, we end up DOS'ing lightdm as it waits for the
442 rest. If we say we're sending less than we do, we confuse the heck out
443 of lightdm, as it starts reading headers from the middle of our
445 stated_length = HEADER_SIZE + get_message_length (message, message_length);
446 if (stated_length != message_length)
448 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
449 "Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu",
450 stated_length, message_length);
454 data = (gchar *) message;
455 data_length = message_length;
456 while (data_length > 0)
460 GError *write_error = NULL;
462 status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &write_error);
464 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
465 "Failed to write to daemon: %s",
466 write_error->message);
467 g_clear_error (&write_error);
468 if (status != G_IO_STATUS_NORMAL)
470 data_length -= n_written;
474 g_debug ("Wrote %zi bytes to daemon", message_length);
475 if (!g_io_channel_flush (priv->to_server_channel, &flush_error))
477 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
478 "Failed to write to daemon: %s",
479 flush_error->message);
480 g_clear_error (&flush_error);
488 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
490 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
492 GString *hint_string;
496 version = read_string (message, message_length, offset);
497 hint_string = g_string_new ("");
498 while (*offset < message_length)
502 name = read_string (message, message_length, offset);
503 value = read_string (message, message_length, offset);
504 g_hash_table_insert (priv->hints, name, value);
505 g_string_append_printf (hint_string, " %s=%s", name, value);
508 priv->connected = TRUE;
509 g_debug ("Connected version=%s%s", version, hint_string->str);
511 g_string_free (hint_string, TRUE);
513 /* Set timeout for default login */
514 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
517 g_debug ("Setting autologin timer for %d seconds", timeout);
518 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
521 /* Notify asynchronous caller */
522 request = g_list_nth_data (priv->connect_requests, 0);
525 request->result = TRUE;
526 request_complete (request);
527 priv->connect_requests = g_list_remove (priv->connect_requests, request);
528 g_object_unref (request);
533 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
535 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
536 guint32 sequence_number, n_messages, i;
539 sequence_number = read_int (message, message_length, offset);
540 if (sequence_number != priv->authenticate_sequence_number)
542 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
546 if (priv->cancelling_authentication)
548 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
552 /* Update username */
553 username = read_string (message, message_length, offset);
554 if (strcmp (username, "") == 0)
559 g_free (priv->authentication_user);
560 priv->authentication_user = username;
562 g_list_free_full (priv->responses_received, g_free);
563 priv->responses_received = NULL;
564 priv->n_responses_waiting = 0;
566 n_messages = read_int (message, message_length, offset);
567 g_debug ("Prompt user with %d message(s)", n_messages);
569 for (i = 0; i < n_messages; i++)
574 style = read_int (message, message_length, offset);
575 text = read_string (message, message_length, offset);
577 // FIXME: Should stop on prompts?
580 case PAM_PROMPT_ECHO_OFF:
581 priv->n_responses_waiting++;
582 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
584 case PAM_PROMPT_ECHO_ON:
585 priv->n_responses_waiting++;
586 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
589 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
592 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
601 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
603 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
604 guint32 sequence_number, return_code;
607 sequence_number = read_int (message, message_length, offset);
609 if (sequence_number != priv->authenticate_sequence_number)
611 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
615 username = read_string (message, message_length, offset);
616 return_code = read_int (message, message_length, offset);
618 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
620 /* Update username */
621 if (strcmp (username, "") == 0)
626 g_free (priv->authentication_user);
627 priv->authentication_user = username;
629 priv->cancelling_authentication = FALSE;
630 priv->is_authenticated = (return_code == 0);
632 priv->in_authentication = FALSE;
633 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
637 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
639 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
643 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
645 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
646 GString *hint_string;
648 g_hash_table_remove_all (priv->hints);
650 hint_string = g_string_new ("");
651 while (*offset < message_length)
655 name = read_string (message, message_length, offset);
656 value = read_string (message, message_length, offset);
657 g_hash_table_insert (priv->hints, name, value);
658 g_string_append_printf (hint_string, " %s=%s", name, value);
661 g_debug ("Reset%s", hint_string->str);
662 g_string_free (hint_string, TRUE);
664 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
668 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
670 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
673 /* Notify asynchronous caller */
674 request = g_list_nth_data (priv->start_session_requests, 0);
679 return_code = read_int (message, message_length, offset);
680 if (return_code == 0)
681 request->result = TRUE;
683 request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_SESSION_FAILED,
684 "Session returned error code %d", return_code);
685 request_complete (request);
686 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
687 g_object_unref (request);
692 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
694 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
697 /* Notify asynchronous caller */
698 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
701 request->dir = read_string (message, message_length, offset);
702 /* Blank data dir means invalid user */
703 if (g_strcmp0 (request->dir, "") == 0)
705 g_free (request->dir);
707 request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_INVALID_USER,
710 request_complete (request);
711 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
712 g_object_unref (request);
717 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
722 id = read_int (message, message_length, &offset);
723 read_int (message, message_length, &offset);
726 case SERVER_MESSAGE_CONNECTED:
727 handle_connected (greeter, message, message_length, &offset);
729 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
730 handle_prompt_authentication (greeter, message, message_length, &offset);
732 case SERVER_MESSAGE_END_AUTHENTICATION:
733 handle_end_authentication (greeter, message, message_length, &offset);
735 case SERVER_MESSAGE_SESSION_RESULT:
736 handle_session_result (greeter, message, message_length, &offset);
738 case SERVER_MESSAGE_SHARED_DIR_RESULT:
739 handle_shared_dir_result (greeter, message, message_length, &offset);
741 case SERVER_MESSAGE_IDLE:
742 handle_idle (greeter, message, message_length, &offset);
744 case SERVER_MESSAGE_RESET:
745 handle_reset (greeter, message, message_length, &offset);
748 g_warning ("Unknown message from server: %d", id);
754 recv_message (LightDMGreeter *greeter, gboolean block, guint8 **message, gsize *length, GError **error)
756 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
757 gsize n_to_read, n_read;
759 if (!connect_to_daemon (greeter, error))
762 /* Read the header, or the whole message if we already have that */
763 n_to_read = HEADER_SIZE;
764 if (priv->n_read >= HEADER_SIZE)
765 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
770 GError *read_error = NULL;
772 status = g_io_channel_read_chars (priv->from_server_channel,
773 (gchar *) priv->read_buffer + priv->n_read,
774 n_to_read - priv->n_read,
777 if (status != G_IO_STATUS_NORMAL)
779 g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
780 "Failed to read from daemon: %s",
781 read_error->message);
782 g_clear_error (&read_error);
786 g_debug ("Read %zi bytes from daemon", n_read);
788 priv->n_read += n_read;
789 } while (priv->n_read < n_to_read && block);
791 /* Stop if haven't got all the data we want */
792 if (priv->n_read != n_to_read)
801 /* If have header, rerun for content */
802 if (priv->n_read == HEADER_SIZE)
804 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
807 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
808 return recv_message (greeter, block, message, length, error);
813 *message = priv->read_buffer;
815 g_free (priv->read_buffer);
817 *length = priv->n_read;
819 priv->read_buffer = g_malloc (priv->n_read);
826 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
828 LightDMGreeter *greeter = data;
830 gsize message_length;
831 GError *error = NULL;
833 /* Read one message and process it */
834 if (!recv_message (greeter, FALSE, &message, &message_length, &error))
836 // FIXME: Should push this up to the client somehow
837 g_warning ("Failed to read from daemon: %s\n", error->message);
838 g_clear_error (&error);
839 return G_SOURCE_REMOVE;
844 handle_message (greeter, message, message_length);
848 return G_SOURCE_CONTINUE;
852 send_connect (LightDMGreeter *greeter, gboolean resettable, GError **error)
854 guint8 message[MAX_MESSAGE_LENGTH];
857 g_debug ("Connecting to display manager...");
858 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset, error) &&
859 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset, error) &&
860 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset, error) &&
861 send_message (greeter, message, offset, error);
865 send_start_session (LightDMGreeter *greeter, const gchar *session, GError **error)
867 guint8 message[MAX_MESSAGE_LENGTH];
871 g_debug ("Starting session %s", session);
873 g_debug ("Starting default session");
875 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset, error) &&
876 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
877 send_message (greeter, message, offset, error);
881 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GError **error)
883 guint8 message[MAX_MESSAGE_LENGTH];
886 g_debug ("Ensuring data directory for user %s", username);
888 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset, error) &&
889 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
890 send_message (greeter, message, offset, error);
894 * lightdm_greeter_connect_to_daemon:
895 * @greeter: The greeter to connect
896 * @cancellable: (allow-none): A #GCancellable or %NULL.
897 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
898 * @user_data: (allow-none): data to pass to the @callback or %NULL.
900 * Asynchronously connects the greeter to the display manager.
902 * 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.
904 * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
907 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
909 LightDMGreeterPrivate *priv;
911 GError *error = NULL;
913 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
915 priv = GET_PRIVATE (greeter);
917 request = request_new (greeter, cancellable, callback, user_data);
918 if (send_connect (greeter, priv->resettable, &error))
919 priv->connect_requests = g_list_append (priv->connect_requests, request);
922 request->error = error;
923 request_complete (request);
924 g_object_unref (request);
929 * lightdm_greeter_connect_to_daemon_finish:
930 * @greeter: The greeter the the request was done with
931 * @result: A #GAsyncResult.
932 * @error: return location for a #GError, or %NULL
934 * Finishes an operation started with lightdm_greeter_connect_to_daemon().
936 * Return value: #TRUE if successfully connected
939 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
941 Request *request = REQUEST (result);
943 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
945 g_propagate_error (error, request->error);
946 return request->result;
950 * lightdm_greeter_connect_to_daemon_sync:
951 * @greeter: The greeter to connect
952 * @error: return location for a #GError, or %NULL
954 * Connects the greeter to the display manager. Will block until connected.
956 * Return value: #TRUE if successfully connected
959 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
961 LightDMGreeterPrivate *priv;
964 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
966 priv = GET_PRIVATE (greeter);
968 /* Read until we are connected */
969 if (!send_connect (greeter, priv->resettable, error))
971 request = request_new (greeter, NULL, NULL, NULL);
972 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
976 gsize message_length;
978 if (!recv_message (greeter, TRUE, &message, &message_length, error))
980 handle_message (greeter, message, message_length);
982 } while (!request->complete);
984 return lightdm_greeter_connect_to_daemon_finish (greeter, G_ASYNC_RESULT (request), error);
988 * lightdm_greeter_connect_sync:
989 * @greeter: The greeter to connect
990 * @error: return location for a #GError, or %NULL
992 * Connects the greeter to the display manager. Will block until connected.
994 * Return value: #TRUE if successfully connected
996 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
999 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
1001 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
1005 * lightdm_greeter_get_hint:
1006 * @greeter: A #LightDMGreeter
1007 * @name: The hint name to query.
1011 * Return value: (nullable): The value for this hint or #NULL if not set.
1014 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
1016 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1017 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
1021 * lightdm_greeter_get_default_session_hint:
1022 * @greeter: A #LightDMGreeter
1024 * Get the default session to use.
1026 * Return value: The session name
1029 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
1031 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1032 return lightdm_greeter_get_hint (greeter, "default-session");
1036 * lightdm_greeter_get_hide_users_hint:
1037 * @greeter: A #LightDMGreeter
1039 * Check if user accounts should be shown. If this is TRUE then the list of
1040 * accounts should be taken from #LightDMUserList and displayed in the greeter
1041 * for the user to choose from. Note that this list can be empty and it is
1042 * recommended you show a method for the user to enter a username manually.
1044 * If this option is shown the greeter should only allow these users to be
1045 * chosen for login unless the manual login hint is set.
1047 * Return value: #TRUE if the available users should not be shown.
1050 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
1054 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1055 value = lightdm_greeter_get_hint (greeter, "hide-users");
1057 return g_strcmp0 (value, "true") == 0;
1061 * lightdm_greeter_get_show_manual_login_hint:
1062 * @greeter: A #LightDMGreeter
1064 * Check if a manual login option should be shown. If set the GUI
1065 * should provide a way for a username to be entered manually.
1066 * Without this hint a greeter which is showing a user list can
1067 * limit logins to only those users.
1069 * Return value: #TRUE if a manual login option should be shown.
1072 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
1076 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1077 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
1079 return g_strcmp0 (value, "true") == 0;
1083 * lightdm_greeter_get_show_remote_login_hint:
1084 * @greeter: A #LightDMGreeter
1086 * Check if a remote login option should be shown. If set the GUI
1087 * should provide a way for a user to log into a remote desktop server.
1089 * Return value: #TRUE if a remote login option should be shown.
1092 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
1096 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1097 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
1099 return g_strcmp0 (value, "true") == 0;
1103 * lightdm_greeter_get_lock_hint:
1104 * @greeter: A #LightDMGreeter
1106 * Check if the greeter is acting as a lock screen.
1108 * Return value: #TRUE if the greeter was triggered by locking the seat.
1111 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
1115 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1116 value = lightdm_greeter_get_hint (greeter, "lock-screen");
1118 return g_strcmp0 (value, "true") == 0;
1122 * lightdm_greeter_get_has_guest_account_hint:
1123 * @greeter: A #LightDMGreeter
1125 * Check if guest sessions are supported.
1127 * Return value: #TRUE if guest sessions are supported.
1130 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
1134 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1135 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
1137 return g_strcmp0 (value, "true") == 0;
1141 * lightdm_greeter_get_select_user_hint:
1142 * @greeter: A #LightDMGreeter
1144 * Get the user to select by default.
1146 * Return value: (nullable): A username or %NULL if no particular user should be selected.
1149 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
1151 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1152 return lightdm_greeter_get_hint (greeter, "select-user");
1156 * lightdm_greeter_get_select_guest_hint:
1157 * @greeter: A #LightDMGreeter
1159 * Check if the guest account should be selected by default.
1161 * Return value: #TRUE if the guest account should be selected by default.
1164 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1168 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1169 value = lightdm_greeter_get_hint (greeter, "select-guest");
1171 return g_strcmp0 (value, "true") == 0;
1175 * lightdm_greeter_get_autologin_user_hint:
1176 * @greeter: A #LightDMGreeter
1178 * Get the user account to automatically log into when the timer expires.
1180 * Return value: (nullable): The user account to automatically log into or %NULL if none configured.
1183 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1185 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1186 return lightdm_greeter_get_hint (greeter, "autologin-user");
1190 * lightdm_greeter_get_autologin_guest_hint:
1191 * @greeter: A #LightDMGreeter
1193 * Check if the guest account should be automatically logged into when the timer expires.
1195 * Return value: #TRUE if the guest account should be automatically logged into.
1198 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1202 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1203 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1205 return g_strcmp0 (value, "true") == 0;
1209 * lightdm_greeter_get_autologin_timeout_hint:
1210 * @greeter: A #LightDMGreeter
1212 * Get the number of seconds to wait before automaitcally logging in.
1214 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1217 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1222 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1223 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1225 timeout = atoi (value);
1233 * lightdm_greeter_cancel_autologin:
1234 * @greeter: A #LightDMGreeter
1236 * Cancel the automatic login.
1239 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1241 LightDMGreeterPrivate *priv;
1243 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1245 priv = GET_PRIVATE (greeter);
1247 if (priv->autologin_timeout)
1248 g_source_remove (priv->autologin_timeout);
1249 priv->autologin_timeout = 0;
1253 * lightdm_greeter_authenticate:
1254 * @greeter: A #LightDMGreeter
1255 * @username: (allow-none): A username or #NULL to prompt for a username.
1256 * @error: return location for a #GError, or %NULL
1258 * Starts the authentication procedure for a user.
1260 * Return value: #TRUE if authentication request sent.
1263 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username, GError **error)
1265 LightDMGreeterPrivate *priv;
1266 guint8 message[MAX_MESSAGE_LENGTH];
1269 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1271 priv = GET_PRIVATE (greeter);
1273 g_return_val_if_fail (priv->connected, FALSE);
1275 priv->cancelling_authentication = FALSE;
1276 priv->authenticate_sequence_number++;
1277 priv->in_authentication = TRUE;
1278 priv->is_authenticated = FALSE;
1279 if (username != priv->authentication_user)
1281 g_free (priv->authentication_user);
1282 priv->authentication_user = g_strdup (username);
1285 g_debug ("Starting authentication for user %s...", username);
1286 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset, error) &&
1287 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1288 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1289 send_message (greeter, message, offset, error);
1293 * lightdm_greeter_authenticate_as_guest:
1294 * @greeter: A #LightDMGreeter
1295 * @error: return location for a #GError, or %NULL
1297 * Starts the authentication procedure for the guest user.
1299 * Return value: #TRUE if authentication request sent.
1302 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter, GError **error)
1304 LightDMGreeterPrivate *priv;
1305 guint8 message[MAX_MESSAGE_LENGTH];
1308 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1310 priv = GET_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 g_free (priv->authentication_user);
1319 priv->authentication_user = NULL;
1321 g_debug ("Starting authentication for guest account...");
1322 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset, error) &&
1323 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1324 send_message (greeter, message, offset, error);
1328 * lightdm_greeter_authenticate_autologin:
1329 * @greeter: A #LightDMGreeter
1330 * @error: return location for a #GError, or %NULL
1332 * Starts the authentication procedure for the automatic login user.
1334 * Return value: #TRUE if authentication request sent.
1337 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter, GError **error)
1341 user = lightdm_greeter_get_autologin_user_hint (greeter);
1342 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1343 return lightdm_greeter_authenticate_as_guest (greeter, error);
1345 return lightdm_greeter_authenticate (greeter, user, error);
1348 g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN,
1349 "Can't authenticate autologin; autologin not configured");
1355 * lightdm_greeter_authenticate_remote:
1356 * @greeter: A #LightDMGreeter
1357 * @session: The name of a remote session
1358 * @username: (allow-none): A username of #NULL to prompt for a username.
1359 * @error: return location for a #GError, or %NULL
1361 * Start authentication for a remote session type.
1363 * Return value: #TRUE if authentication request sent.
1366 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username, GError **error)
1368 LightDMGreeterPrivate *priv;
1369 guint8 message[MAX_MESSAGE_LENGTH];
1372 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1374 priv = GET_PRIVATE (greeter);
1376 g_return_val_if_fail (priv->connected, FALSE);
1378 priv->cancelling_authentication = FALSE;
1379 priv->authenticate_sequence_number++;
1380 priv->in_authentication = TRUE;
1381 priv->is_authenticated = FALSE;
1382 g_free (priv->authentication_user);
1383 priv->authentication_user = NULL;
1386 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1388 g_debug ("Starting authentication for remote session %s...", session);
1390 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset, error) &&
1391 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1392 write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
1393 write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1394 send_message (greeter, message, offset, error);
1398 * lightdm_greeter_respond:
1399 * @greeter: A #LightDMGreeter
1400 * @response: Response to a prompt
1401 * @error: return location for a #GError, or %NULL
1403 * Provide response to a prompt. May be one in a series.
1405 * Return value: #TRUE if response sent.
1408 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response, GError **error)
1410 LightDMGreeterPrivate *priv;
1411 guint8 message[MAX_MESSAGE_LENGTH];
1414 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1415 g_return_val_if_fail (response != NULL, FALSE);
1417 priv = GET_PRIVATE (greeter);
1419 g_return_val_if_fail (priv->connected, FALSE);
1420 g_return_val_if_fail (priv->n_responses_waiting > 0, FALSE);
1422 priv->n_responses_waiting--;
1423 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1425 if (priv->n_responses_waiting == 0)
1430 g_debug ("Providing response to display manager");
1432 msg_length = int_length ();
1433 for (iter = priv->responses_received; iter; iter = iter->next)
1434 msg_length += string_length ((gchar *)iter->data);
1436 if (!write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset, error) ||
1437 !write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset, error))
1439 for (iter = priv->responses_received; iter; iter = iter->next)
1441 if (!write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset, error))
1444 if (!send_message (greeter, message, offset, error))
1447 g_list_free_full (priv->responses_received, g_free);
1448 priv->responses_received = NULL;
1455 * lightdm_greeter_cancel_authentication:
1456 * @greeter: A #LightDMGreeter
1457 * @error: return location for a #GError, or %NULL
1459 * Cancel the current user authentication.
1461 * Return value: #TRUE if cancel request sent.
1464 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter, GError **error)
1466 LightDMGreeterPrivate *priv;
1467 guint8 message[MAX_MESSAGE_LENGTH];
1470 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1472 priv = GET_PRIVATE (greeter);
1474 g_return_val_if_fail (priv->connected, FALSE);
1476 priv->cancelling_authentication = TRUE;
1477 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset, error) &&
1478 send_message (greeter, message, offset, error);
1482 * lightdm_greeter_get_in_authentication:
1483 * @greeter: A #LightDMGreeter
1485 * Checks if the greeter is in the process of authenticating.
1487 * Return value: #TRUE if the greeter is authenticating a user.
1490 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1492 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1493 return GET_PRIVATE (greeter)->in_authentication;
1497 * lightdm_greeter_get_is_authenticated:
1498 * @greeter: A #LightDMGreeter
1500 * Checks if the greeter has successfully authenticated.
1502 * Return value: #TRUE if the greeter is authenticated for login.
1505 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1507 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1508 return GET_PRIVATE (greeter)->is_authenticated;
1512 * lightdm_greeter_get_authentication_user:
1513 * @greeter: A #LightDMGreeter
1515 * Get the user that is being authenticated.
1517 * Return value: (nullable): The username of the authentication user being authenticated or #NULL if no authentication in progress.
1520 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1522 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1523 return GET_PRIVATE (greeter)->authentication_user;
1527 * lightdm_greeter_set_language:
1528 * @greeter: A #LightDMGreeter
1529 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1530 * @error: return location for a #GError, or %NULL
1532 * Set the language for the currently authenticated user.
1534 * Return value: #TRUE if set language request sent.
1537 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language, GError **error)
1539 LightDMGreeterPrivate *priv;
1540 guint8 message[MAX_MESSAGE_LENGTH];
1543 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1545 priv = GET_PRIVATE (greeter);
1547 g_return_val_if_fail (priv->connected, FALSE);
1549 return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset, error) &&
1550 write_string (message, MAX_MESSAGE_LENGTH, language, &offset, error) &&
1551 send_message (greeter, message, offset, error);
1555 * lightdm_greeter_start_session:
1556 * @greeter: A #LightDMGreeter
1557 * @session: (allow-none): The session to log into or #NULL to use the default.
1558 * @cancellable: (allow-none): A #GCancellable or %NULL.
1559 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1560 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1562 * Asynchronously start a session for the authenticated user.
1564 * 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.
1566 * See lightdm_greeter_start_session_sync() for the synchronous version.
1569 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1571 LightDMGreeterPrivate *priv;
1573 GError *error = NULL;
1575 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1577 priv = GET_PRIVATE (greeter);
1579 request = request_new (greeter, cancellable, callback, user_data);
1580 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1581 if (!send_start_session (greeter, session, &error))
1583 request->error = error;
1584 request_complete (request);
1589 * lightdm_greeter_start_session_finish:
1590 * @greeter: A #LightDMGreeter
1591 * @result: A #GAsyncResult.
1592 * @error: return location for a #GError, or %NULL
1594 * Start a session for the authenticated user.
1596 * Return value: TRUE if the session was started.
1599 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1601 Request *request = REQUEST (result);
1603 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1605 g_propagate_error (error, request->error);
1606 return request->result;
1610 * lightdm_greeter_start_session_sync:
1611 * @greeter: A #LightDMGreeter
1612 * @session: (allow-none): The session to log into or #NULL to use the default.
1613 * @error: return location for a #GError, or %NULL
1615 * Start a session for the authenticated user.
1617 * Return value: TRUE if the session was started.
1620 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1622 LightDMGreeterPrivate *priv;
1625 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1627 priv = GET_PRIVATE (greeter);
1629 g_return_val_if_fail (priv->connected, FALSE);
1630 g_return_val_if_fail (priv->is_authenticated, FALSE);
1632 /* Read until the session is started */
1633 if (!send_start_session (greeter, session, error))
1635 request = request_new (greeter, NULL, NULL, NULL);
1636 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1640 gsize message_length;
1642 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1644 handle_message (greeter, message, message_length);
1646 } while (!request->complete);
1648 return lightdm_greeter_start_session_finish (greeter, G_ASYNC_RESULT (request), error);
1652 * lightdm_greeter_ensure_shared_data_dir:
1653 * @greeter: A #LightDMGreeter
1654 * @username: A username
1655 * @cancellable: (allow-none): A #GCancellable or %NULL.
1656 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1657 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1659 * Ensure that a shared data dir for the given user is available. Both the
1660 * greeter user and @username will have write access to that folder. The
1661 * intention is that larger pieces of shared data would be stored there (files
1662 * that the greeter creates but wants to give to a user -- like camera
1663 * photos -- or files that the user creates but wants the greeter to
1664 * see -- like contact avatars).
1666 * LightDM will automatically create these if the user actually logs in, so
1667 * greeters only need to call this method if they want to store something in
1668 * the directory themselves.
1671 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1673 LightDMGreeterPrivate *priv;
1675 GError *error = NULL;
1677 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1679 priv = GET_PRIVATE (greeter);
1681 request = request_new (greeter, cancellable, callback, user_data);
1682 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1683 if (!send_ensure_shared_data_dir (greeter, username, &error))
1685 request->error = error;
1686 request_complete (request);
1691 * lightdm_greeter_ensure_shared_data_dir_finish:
1692 * @result: A #GAsyncResult.
1693 * @greeter: A #LightDMGreeter
1694 * @error: return location for a #GError, or %NULL
1696 * Function to call from lightdm_greeter_ensure_shared_data_dir callback.
1698 * Return value: The path to the shared directory, free with g_free.
1701 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1703 Request *request = REQUEST (result);
1705 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1707 g_propagate_error (error, request->error);
1708 return g_strdup (request->dir);
1712 * lightdm_greeter_ensure_shared_data_dir_sync:
1713 * @greeter: A #LightDMGreeter
1714 * @username: A username
1715 * @error: return location for a #GError, or %NULL
1717 * Ensure that a shared data dir for the given user is available. Both the
1718 * greeter user and @username will have write access to that folder. The
1719 * intention is that larger pieces of shared data would be stored there (files
1720 * that the greeter creates but wants to give to a user -- like camera
1721 * photos -- or files that the user creates but wants the greeter to
1722 * see -- like contact avatars).
1724 * LightDM will automatically create these if the user actually logs in, so
1725 * greeters only need to call this method if they want to store something in
1726 * the directory themselves.
1728 * Return value: The path to the shared directory, free with g_free.
1731 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username, GError **error)
1733 LightDMGreeterPrivate *priv;
1736 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1738 priv = GET_PRIVATE (greeter);
1740 g_return_val_if_fail (priv->connected, NULL);
1742 /* Read until a response */
1743 if (!send_ensure_shared_data_dir (greeter, username, error))
1745 request = request_new (greeter, NULL, NULL, NULL);
1746 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1750 gsize message_length;
1752 if (!recv_message (greeter, TRUE, &message, &message_length, error))
1754 handle_message (greeter, message, message_length);
1756 } while (!request->complete);
1758 return lightdm_greeter_ensure_shared_data_dir_finish (greeter, G_ASYNC_RESULT (request), error);
1762 lightdm_greeter_init (LightDMGreeter *greeter)
1764 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1766 priv->read_buffer = g_malloc (HEADER_SIZE);
1767 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1771 lightdm_greeter_set_property (GObject *object,
1773 const GValue *value,
1776 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1780 lightdm_greeter_get_property (GObject *object,
1785 LightDMGreeter *self;
1787 self = LIGHTDM_GREETER (object);
1790 case PROP_DEFAULT_SESSION_HINT:
1791 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1793 case PROP_HIDE_USERS_HINT:
1794 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1796 case PROP_SHOW_MANUAL_LOGIN_HINT:
1797 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1799 case PROP_SHOW_REMOTE_LOGIN_HINT:
1800 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1802 case PROP_LOCK_HINT:
1803 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1805 case PROP_HAS_GUEST_ACCOUNT_HINT:
1806 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1808 case PROP_SELECT_USER_HINT:
1809 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1811 case PROP_SELECT_GUEST_HINT:
1812 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1814 case PROP_AUTOLOGIN_USER_HINT:
1815 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1817 case PROP_AUTOLOGIN_GUEST_HINT:
1818 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1820 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1821 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1823 case PROP_AUTHENTICATION_USER:
1824 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1826 case PROP_IN_AUTHENTICATION:
1827 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1829 case PROP_IS_AUTHENTICATED:
1830 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1833 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1839 lightdm_greeter_finalize (GObject *object)
1841 LightDMGreeter *self = LIGHTDM_GREETER (object);
1842 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1844 if (priv->to_server_channel)
1845 g_io_channel_unref (priv->to_server_channel);
1846 if (priv->from_server_channel)
1847 g_io_channel_unref (priv->from_server_channel);
1848 g_free (priv->authentication_user);
1849 g_hash_table_unref (priv->hints);
1851 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1855 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1857 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1859 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1861 object_class->set_property = lightdm_greeter_set_property;
1862 object_class->get_property = lightdm_greeter_get_property;
1863 object_class->finalize = lightdm_greeter_finalize;
1865 g_object_class_install_property (object_class,
1866 PROP_DEFAULT_SESSION_HINT,
1867 g_param_spec_string ("default-session-hint",
1868 "default-session-hint",
1869 "Default session hint",
1873 g_object_class_install_property (object_class,
1874 PROP_HIDE_USERS_HINT,
1875 g_param_spec_boolean ("hide-users-hint",
1881 g_object_class_install_property (object_class,
1882 PROP_SHOW_MANUAL_LOGIN_HINT,
1883 g_param_spec_boolean ("show-manual-login-hint",
1884 "show-manual-login-hint",
1885 "Show manual login hint",
1889 g_object_class_install_property (object_class,
1890 PROP_SHOW_REMOTE_LOGIN_HINT,
1891 g_param_spec_boolean ("show-remote-login-hint",
1892 "show-remote-login-hint",
1893 "Show remote login hint",
1897 g_object_class_install_property (object_class,
1899 g_param_spec_boolean ("lock-hint",
1905 g_object_class_install_property (object_class,
1906 PROP_HAS_GUEST_ACCOUNT_HINT,
1907 g_param_spec_boolean ("has-guest-account-hint",
1908 "has-guest-account-hint",
1909 "Has guest account hint",
1913 g_object_class_install_property (object_class,
1914 PROP_SELECT_USER_HINT,
1915 g_param_spec_string ("select-user-hint",
1921 g_object_class_install_property (object_class,
1922 PROP_SELECT_GUEST_HINT,
1923 g_param_spec_boolean ("select-guest-hint",
1924 "select-guest-hint",
1925 "Select guest account hint",
1929 g_object_class_install_property (object_class,
1930 PROP_AUTOLOGIN_USER_HINT,
1931 g_param_spec_string ("autologin-user-hint",
1932 "autologin-user-hint",
1933 "Autologin user hint",
1937 g_object_class_install_property (object_class,
1938 PROP_AUTOLOGIN_GUEST_HINT,
1939 g_param_spec_boolean ("autologin-guest-hint",
1940 "autologin-guest-hint",
1941 "Autologin guest account hint",
1945 g_object_class_install_property (object_class,
1946 PROP_AUTOLOGIN_TIMEOUT_HINT,
1947 g_param_spec_int ("autologin-timeout-hint",
1948 "autologin-timeout-hint",
1949 "Autologin timeout hint",
1953 g_object_class_install_property (object_class,
1954 PROP_AUTHENTICATION_USER,
1955 g_param_spec_string ("authentication-user",
1956 "authentication-user",
1957 "The user being authenticated",
1960 g_object_class_install_property (object_class,
1961 PROP_IN_AUTHENTICATION,
1962 g_param_spec_boolean ("in-authentication",
1963 "in-authentication",
1964 "TRUE if a user is being authenticated",
1967 g_object_class_install_property (object_class,
1968 PROP_IS_AUTHENTICATED,
1969 g_param_spec_boolean ("is-authenticated",
1971 "TRUE if the selected user is authenticated",
1976 * LightDMGreeter::show-prompt:
1977 * @greeter: A #LightDMGreeter
1978 * @text: Prompt text
1979 * @type: Prompt type
1981 * The ::show-prompt signal gets emitted when the greeter should show a
1982 * prompt to the user. The given text should be displayed and an input
1983 * field for the user to provide a response.
1985 * Call lightdm_greeter_respond() with the resultant input or
1986 * lightdm_greeter_cancel_authentication() to abort the authentication.
1988 signals[SHOW_PROMPT] =
1989 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
1990 G_TYPE_FROM_CLASS (klass),
1992 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1995 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_prompt_type_get_type ());
1998 * LightDMGreeter::show-message:
1999 * @greeter: A #LightDMGreeter
2000 * @text: Message text
2001 * @type: Message type
2003 * The ::show-message signal gets emitted when the greeter
2004 * should show a message to the user.
2006 signals[SHOW_MESSAGE] =
2007 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
2008 G_TYPE_FROM_CLASS (klass),
2010 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
2013 G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_message_type_get_type ());
2016 * LightDMGreeter::authentication-complete:
2017 * @greeter: A #LightDMGreeter
2019 * The ::authentication-complete signal gets emitted when the greeter
2020 * has completed authentication.
2022 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
2025 signals[AUTHENTICATION_COMPLETE] =
2026 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
2027 G_TYPE_FROM_CLASS (klass),
2029 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
2035 * LightDMGreeter::autologin-timer-expired:
2036 * @greeter: A #LightDMGreeter
2038 * The ::timed-login signal gets emitted when the automatic login timer has expired.
2039 * The application should then call lightdm_greeter_login().
2041 signals[AUTOLOGIN_TIMER_EXPIRED] =
2042 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
2043 G_TYPE_FROM_CLASS (klass),
2045 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
2051 * LightDMGreeter::idle:
2052 * @greeter: A #LightDMGreeter
2054 * The ::idle signal gets emitted when the user has logged in and the
2055 * greeter is no longer needed.
2057 * This signal only matters if the greeter has marked itself as
2058 * resettable using lightdm_greeter_set_resettable().
2061 g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
2062 G_TYPE_FROM_CLASS (klass),
2064 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
2070 * LightDMGreeter::reset:
2071 * @greeter: A #LightDMGreeter
2073 * The ::reset signal gets emitted when the user is returning to a greeter
2074 * that was previously marked idle.
2076 * This signal only matters if the greeter has marked itself as
2077 * resettable using lightdm_greeter_set_resettable().
2080 g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
2081 G_TYPE_FROM_CLASS (klass),
2083 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
2090 request_init (Request *request)
2095 request_finalize (GObject *object)
2097 Request *request = REQUEST (object);
2099 g_clear_object (&request->greeter);
2100 g_clear_object (&request->cancellable);
2101 g_free (request->dir);
2103 G_OBJECT_CLASS (request_parent_class)->finalize (object);
2107 request_class_init (RequestClass *klass)
2109 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2110 object_class->finalize = request_finalize;
2114 request_get_user_data (GAsyncResult *result)
2116 return REQUEST (result)->user_data;
2120 request_get_source_object (GAsyncResult *result)
2122 return g_object_ref (REQUEST (result)->greeter);
2126 request_iface_init (GAsyncResultIface *iface)
2128 iface->get_user_data = request_get_user_data;
2129 iface->get_source_object = request_get_source_object;