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 3 of the License, or (at your option) any
8 * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
16 #include <security/pam_appl.h>
18 #include "lightdm/greeter.h"
22 PROP_DEFAULT_SESSION_HINT,
24 PROP_SHOW_MANUAL_LOGIN_HINT,
26 PROP_HAS_GUEST_ACCOUNT_HINT,
27 PROP_SELECT_USER_HINT,
28 PROP_SELECT_GUEST_HINT,
29 PROP_AUTOLOGIN_USER_HINT,
30 PROP_AUTOLOGIN_GUEST_HINT,
31 PROP_AUTOLOGIN_TIMEOUT_HINT,
32 PROP_AUTHENTICATION_USER,
33 PROP_IN_AUTHENTICATION,
34 PROP_IS_AUTHENTICATED,
40 AUTHENTICATION_COMPLETE,
41 AUTOLOGIN_TIMER_EXPIRED,
44 static guint signals[LAST_SIGNAL] = { 0 };
50 GIOChannel *to_server_channel, *from_server_channel;
54 gsize n_responses_waiting;
55 GList *responses_received;
58 guint autologin_timeout;
60 gchar *authentication_user;
61 gboolean in_authentication;
62 gboolean is_authenticated;
63 guint32 authenticate_sequence_number;
64 gboolean cancelling_authentication;
65 } LightDMGreeterPrivate;
67 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
69 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
72 #define MAX_MESSAGE_LENGTH 1024
74 /* Messages from the greeter to the server */
77 GREETER_MESSAGE_CONNECT = 0,
78 GREETER_MESSAGE_AUTHENTICATE,
79 GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
80 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
81 GREETER_MESSAGE_START_SESSION,
82 GREETER_MESSAGE_CANCEL_AUTHENTICATION,
83 GREETER_MESSAGE_SET_LANGUAGE
86 /* Messages from the server to the greeter */
89 SERVER_MESSAGE_CONNECTED = 0,
90 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
91 SERVER_MESSAGE_END_AUTHENTICATION,
92 SERVER_MESSAGE_SESSION_RESULT
96 * lightdm_greeter_new:
98 * Create a new greeter.
100 * Return value: the new #LightDMGreeter
103 lightdm_greeter_new ()
105 return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
109 timed_login_cb (gpointer data)
111 LightDMGreeter *greeter = data;
112 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
114 priv->autologin_timeout = 0;
115 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
127 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
129 if (*offset + 4 >= buffer_length)
131 buffer[*offset] = value >> 24;
132 buffer[*offset+1] = (value >> 16) & 0xFF;
133 buffer[*offset+2] = (value >> 8) & 0xFF;
134 buffer[*offset+3] = value & 0xFF;
139 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
144 length = strlen (value);
145 write_int (buffer, buffer_length, length, offset);
146 if (*offset + length >= buffer_length)
148 memcpy (buffer + *offset, value, length);
153 read_int (guint8 *message, gsize message_length, gsize *offset)
158 if (message_length - *offset < int_length ())
160 g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
164 buffer = message + *offset;
165 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
166 *offset += int_length ();
172 read_string (guint8 *message, gsize message_length, gsize *offset)
177 length = read_int (message, message_length, offset);
178 if (message_length - *offset < length)
180 g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
181 return g_strdup ("");
184 value = g_malloc (sizeof (gchar) * (length + 1));
185 memcpy (value, message + *offset, length);
186 value[length] = '\0';
193 string_length (const gchar *value)
196 return int_length () + strlen (value);
198 return int_length ();
202 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
204 write_int (buffer, buffer_length, id, offset);
205 write_int (buffer, buffer_length, length, offset);
209 get_message_length (guint8 *message, gsize message_length)
212 return read_int (message, message_length, &offset);
216 write_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
218 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
220 GError *error = NULL;
221 guint32 stated_length;
223 /* Double check that we're sending well-formed messages. If we say we're
224 sending more than we do, we end up DOS'ing lightdm as it waits for the
225 rest. If we say we're sending less than we do, we confuse the heck out
226 of lightdm, as it starts reading headers from the middle of our
228 stated_length = HEADER_SIZE + get_message_length (message, message_length);
229 if (stated_length != message_length)
231 g_warning ("Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu", stated_length, message_length);
235 status = g_io_channel_write_chars (priv->to_server_channel, (gchar *) message, message_length, NULL, &error);
237 g_warning ("Error writing to daemon: %s", error->message);
238 g_clear_error (&error);
239 if (status == G_IO_STATUS_NORMAL)
240 g_debug ("Wrote %zi bytes to daemon", message_length);
241 g_io_channel_flush (priv->to_server_channel, NULL);
245 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
247 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
249 GString *hint_string;
252 version = read_string (message, message_length, offset);
253 hint_string = g_string_new ("");
254 while (*offset < message_length)
258 name = read_string (message, message_length, offset);
259 value = read_string (message, message_length, offset);
260 g_hash_table_insert (priv->hints, name, value);
261 g_string_append_printf (hint_string, " %s=%s", name, value);
264 g_debug ("Connected version=%s%s", version, hint_string->str);
266 g_string_free (hint_string, TRUE);
268 /* Set timeout for default login */
269 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
272 g_debug ("Setting autologin timer for %d seconds", timeout);
273 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
278 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
280 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
281 guint32 sequence_number, n_messages, i;
284 sequence_number = read_int (message, message_length, offset);
285 if (sequence_number != priv->authenticate_sequence_number)
287 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
291 if (priv->cancelling_authentication)
293 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
297 /* Update username */
298 username = read_string (message, message_length, offset);
299 if (strcmp (username, "") == 0)
304 g_free (priv->authentication_user);
305 priv->authentication_user = username;
307 g_list_free_full (priv->responses_received, g_free);
308 priv->responses_received = NULL;
309 priv->n_responses_waiting = 0;
311 n_messages = read_int (message, message_length, offset);
312 g_debug ("Prompt user with %d message(s)", n_messages);
314 for (i = 0; i < n_messages; i++)
319 style = read_int (message, message_length, offset);
320 text = read_string (message, message_length, offset);
322 // FIXME: Should stop on prompts?
325 case PAM_PROMPT_ECHO_OFF:
326 priv->n_responses_waiting++;
327 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
329 case PAM_PROMPT_ECHO_ON:
330 priv->n_responses_waiting++;
331 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
334 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
337 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
346 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
348 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
349 guint32 sequence_number, return_code;
352 sequence_number = read_int (message, message_length, offset);
354 if (sequence_number != priv->authenticate_sequence_number)
356 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
360 username = read_string (message, message_length, offset);
361 return_code = read_int (message, message_length, offset);
363 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
365 /* Update username */
366 if (strcmp (username, "") == 0)
371 g_free (priv->authentication_user);
372 priv->authentication_user = username;
374 priv->cancelling_authentication = FALSE;
375 priv->is_authenticated = (return_code == 0);
377 priv->in_authentication = FALSE;
378 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
382 read_message (LightDMGreeter *greeter, gsize *length, gboolean block)
384 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
385 gsize n_to_read, n_read;
387 GError *error = NULL;
389 /* Read the header, or the whole message if we already have that */
390 n_to_read = HEADER_SIZE;
391 if (priv->n_read >= HEADER_SIZE)
392 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
397 status = g_io_channel_read_chars (priv->from_server_channel,
398 (gchar *) priv->read_buffer + priv->n_read,
399 n_to_read - priv->n_read,
403 g_warning ("Error reading from server: %s", error->message);
404 g_clear_error (&error);
405 if (status != G_IO_STATUS_NORMAL)
408 g_debug ("Read %zi bytes from daemon", n_read);
410 priv->n_read += n_read;
411 } while (priv->n_read < n_to_read && block);
413 /* Stop if haven't got all the data we want */
414 if (priv->n_read != n_to_read)
417 /* If have header, rerun for content */
418 if (priv->n_read == HEADER_SIZE)
420 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
423 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
424 return read_message (greeter, length, block);
428 buffer = priv->read_buffer;
429 *length = priv->n_read;
431 priv->read_buffer = g_malloc (priv->n_read);
438 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
440 LightDMGreeter *greeter = data;
442 gsize message_length, offset;
445 message = read_message (greeter, &message_length, FALSE);
450 id = read_int (message, message_length, &offset);
451 read_int (message, message_length, &offset);
454 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
455 handle_prompt_authentication (greeter, message, message_length, &offset);
457 case SERVER_MESSAGE_END_AUTHENTICATION:
458 handle_end_authentication (greeter, message, message_length, &offset);
461 g_warning ("Unknown message from server: %d", id);
470 * lightdm_greeter_connect_sync:
471 * @greeter: The greeter to connect
472 * @error: return location for a #GError, or %NULL
474 * Connects the greeter to the display manager. Will block until connected.
476 * Return value: #TRUE if successfully connected
479 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
481 LightDMGreeterPrivate *priv;
483 guint8 message[MAX_MESSAGE_LENGTH];
485 gsize response_length, offset = 0;
488 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
490 priv = GET_PRIVATE (greeter);
492 fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
495 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
498 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
499 g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
501 fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
504 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
507 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
508 g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
509 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
511 g_debug ("Connecting to display manager...");
512 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION), &offset);
513 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
514 write_message (greeter, message, offset);
516 response = read_message (greeter, &response_length, TRUE);
521 id = read_int (response, response_length, &offset);
522 read_int (response, response_length, &offset);
523 if (id == SERVER_MESSAGE_CONNECTED)
524 handle_connected (greeter, response, response_length, &offset);
526 if (id != SERVER_MESSAGE_CONNECTED)
528 g_warning ("Expected CONNECTED message, got %d", id);
532 priv->connected = TRUE;
538 * lightdm_greeter_get_hint:
539 * @greeter: A #LightDMGreeter
540 * @name: The hint name to query.
544 * Return value: The value for this hint or #NULL if not set.
547 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
549 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
550 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
554 * lightdm_greeter_get_default_session_hint:
555 * @greeter: A #LightDMGreeter
557 * Get the default session to use.
559 * Return value: The session name
562 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
564 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
565 return lightdm_greeter_get_hint (greeter, "default-session");
569 * lightdm_greeter_get_hide_users_hint:
570 * @greeter: A #LightDMGreeter
572 * Check if user accounts should be shown. If this is TRUE then the list of
573 * accounts should be taken from #LightDMUserList and displayed in the greeter
574 * for the user to choose from. Note that this list can be empty and it is
575 * recommended you show a method for the user to enter a username manually.
577 * If this option is shown the greeter should only allow these users to be
578 * chosen for login unless the manual login hint is set.
580 * Return value: #TRUE if the available users should not be shown.
583 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
587 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
588 value = lightdm_greeter_get_hint (greeter, "hide-users");
590 return g_strcmp0 (value, "true") == 0;
594 * lightdm_greeter_get_show_manual_login_hint:
595 * @greeter: A #LightDMGreeter
597 * Check if a manual login option should be shown. If set the GUI
598 * should provide a way for a username to be entered manually.
599 * Without this hint a greeter which is showing a user list can
600 * limit logins to only those users.
602 * Return value: #TRUE if a manual login option should be shown.
605 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
609 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
610 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
612 return g_strcmp0 (value, "true") == 0;
616 * lightdm_greeter_get_lock_hint:
617 * @greeter: A #LightDMGreeter
619 * Check if the greeter is acting as a lock screen.
621 * Return value: #TRUE if the greeter was triggered by locking the seat.
624 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
628 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
629 value = lightdm_greeter_get_hint (greeter, "lock-screen");
631 return g_strcmp0 (value, "true") == 0;
635 * lightdm_greeter_get_has_guest_account_hint:
636 * @greeter: A #LightDMGreeter
638 * Check if guest sessions are supported.
640 * Return value: #TRUE if guest sessions are supported.
643 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
647 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
648 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
650 return g_strcmp0 (value, "true") == 0;
654 * lightdm_greeter_get_select_user_hint:
655 * @greeter: A #LightDMGreeter
657 * Get the user to select by default.
659 * Return value: A username
662 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
664 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
665 return lightdm_greeter_get_hint (greeter, "select-user");
669 * lightdm_greeter_get_select_guest_hint:
670 * @greeter: A #LightDMGreeter
672 * Check if the guest account should be selected by default.
674 * Return value: #TRUE if the guest account should be selected by default.
677 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
681 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
682 value = lightdm_greeter_get_hint (greeter, "select-guest");
684 return g_strcmp0 (value, "true") == 0;
688 * lightdm_greeter_get_autologin_user_hint:
689 * @greeter: A #LightDMGreeter
691 * Get the user account to automatically logg into when the timer expires.
693 * Return value: The user account to automatically log into.
696 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
698 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
699 return lightdm_greeter_get_hint (greeter, "autologin-user");
703 * lightdm_greeter_get_autologin_guest_hint:
704 * @greeter: A #LightDMGreeter
706 * Check if the guest account should be automatically logged into when the timer expires.
708 * Return value: #TRUE if the guest account should be automatically logged into.
711 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
715 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
716 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
718 return g_strcmp0 (value, "true") == 0;
722 * lightdm_greeter_get_autologin_timeout_hint:
723 * @greeter: A #LightDMGreeter
725 * Get the number of seconds to wait before automaitcally logging in.
727 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
730 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
735 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
736 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
738 timeout = atoi (value);
746 * lightdm_greeter_cancel_autologin:
747 * @greeter: A #LightDMGreeter
749 * Cancel the automatic login.
752 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
754 LightDMGreeterPrivate *priv;
756 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
758 priv = GET_PRIVATE (greeter);
760 if (priv->autologin_timeout)
761 g_source_remove (priv->autologin_timeout);
762 priv->autologin_timeout = 0;
766 * lightdm_greeter_authenticate:
767 * @greeter: A #LightDMGreeter
768 * @username: (allow-none): A username or #NULL to prompt for a username.
770 * Starts the authentication procedure for a user.
773 lightdm_greeter_authenticate (LightDMGreeter *greeter, const char *username)
775 LightDMGreeterPrivate *priv;
776 guint8 message[MAX_MESSAGE_LENGTH];
779 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
781 priv = GET_PRIVATE (greeter);
783 g_return_if_fail (priv->connected);
785 priv->cancelling_authentication = FALSE;
786 priv->authenticate_sequence_number++;
787 priv->in_authentication = TRUE;
788 priv->is_authenticated = FALSE;
789 if (username != priv->authentication_user)
791 g_free (priv->authentication_user);
792 priv->authentication_user = g_strdup (username);
795 g_debug ("Starting authentication for user %s...", username);
796 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
797 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
798 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
799 write_message (greeter, message, offset);
803 * lightdm_greeter_authenticate_as_guest:
804 * @greeter: A #LightDMGreeter
806 * Starts the authentication procedure for the guest user.
809 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
811 LightDMGreeterPrivate *priv;
812 guint8 message[MAX_MESSAGE_LENGTH];
815 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
817 priv = GET_PRIVATE (greeter);
819 g_return_if_fail (priv->connected);
821 priv->cancelling_authentication = FALSE;
822 priv->authenticate_sequence_number++;
823 priv->in_authentication = TRUE;
824 priv->is_authenticated = FALSE;
825 g_free (priv->authentication_user);
826 priv->authentication_user = NULL;
828 g_debug ("Starting authentication for guest account...");
829 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
830 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
831 write_message (greeter, message, offset);
835 * lightdm_greeter_respond:
836 * @greeter: A #LightDMGreeter
837 * @response: Response to a prompt
839 * Provide response to a prompt. May be one in a series.
842 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
844 LightDMGreeterPrivate *priv;
845 guint8 message[MAX_MESSAGE_LENGTH];
848 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
849 g_return_if_fail (response != NULL);
851 priv = GET_PRIVATE (greeter);
853 g_return_if_fail (priv->connected);
854 g_return_if_fail (priv->n_responses_waiting > 0);
856 priv->n_responses_waiting--;
857 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
859 if (priv->n_responses_waiting == 0)
864 g_debug ("Providing response to display manager");
866 msg_length = int_length ();
867 for (iter = priv->responses_received; iter; iter = iter->next)
869 msg_length += string_length ((gchar *)iter->data);
872 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
873 write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
874 for (iter = priv->responses_received; iter; iter = iter->next)
876 write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
878 write_message (greeter, message, offset);
880 g_list_free_full (priv->responses_received, g_free);
881 priv->responses_received = NULL;
886 * lightdm_greeter_cancel_authentication:
887 * @greeter: A #LightDMGreeter
889 * Cancel the current user authentication.
892 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
894 LightDMGreeterPrivate *priv;
895 guint8 message[MAX_MESSAGE_LENGTH];
898 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
900 priv = GET_PRIVATE (greeter);
902 g_return_if_fail (priv->connected);
904 priv->cancelling_authentication = TRUE;
905 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
906 write_message (greeter, message, offset);
910 * lightdm_greeter_get_in_authentication:
911 * @greeter: A #LightDMGreeter
913 * Checks if the greeter is in the process of authenticating.
915 * Return value: #TRUE if the greeter is authenticating a user.
918 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
920 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
921 return GET_PRIVATE (greeter)->in_authentication;
925 * lightdm_greeter_get_is_authenticated:
926 * @greeter: A #LightDMGreeter
928 * Checks if the greeter has successfully authenticated.
930 * Return value: #TRUE if the greeter is authenticated for login.
933 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
935 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
936 return GET_PRIVATE (greeter)->is_authenticated;
940 * lightdm_greeter_get_authentication_user:
941 * @greeter: A #LightDMGreeter
943 * Get the user that is being authenticated.
945 * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
948 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
950 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
951 return GET_PRIVATE (greeter)->authentication_user;
955 * lightdm_greeter_set_language:
956 * @greeter: A #LightDMGreeter
957 * @language: The language to use for this user.
959 * Set the language for the currently authenticated user.
962 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
964 LightDMGreeterPrivate *priv;
965 guint8 message[MAX_MESSAGE_LENGTH];
968 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
970 priv = GET_PRIVATE (greeter);
972 g_return_if_fail (priv->connected);
974 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
975 write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
976 write_message (greeter, message, offset);
980 * lightdm_greeter_start_session_sync:
981 * @greeter: A #LightDMGreeter
982 * @session: (allow-none): The session to log into or #NULL to use the default.
983 * @error: return location for a #GError, or %NULL
985 * Start a session for the authenticated user.
987 * Return value: TRUE if the session was started.
990 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
992 LightDMGreeterPrivate *priv;
993 guint8 message[MAX_MESSAGE_LENGTH];
995 gsize response_length, offset = 0;
996 guint32 id, return_code = 1;
998 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1000 priv = GET_PRIVATE (greeter);
1002 g_return_val_if_fail (priv->connected, FALSE);
1003 g_return_val_if_fail (priv->is_authenticated, FALSE);
1006 g_debug ("Starting session %s", session);
1008 g_debug ("Starting default session");
1010 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
1011 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1012 write_message (greeter, message, offset);
1014 response = read_message (greeter, &response_length, TRUE);
1019 id = read_int (response, response_length, &offset);
1020 read_int (response, response_length, &offset);
1021 if (id == SERVER_MESSAGE_SESSION_RESULT)
1022 return_code = read_int (response, response_length, &offset);
1024 g_warning ("Expected SESSION_RESULT message, got %d", id);
1028 return return_code == 0;
1032 lightdm_greeter_init (LightDMGreeter *greeter)
1034 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1036 priv->read_buffer = g_malloc (HEADER_SIZE);
1037 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1041 lightdm_greeter_set_property (GObject *object,
1043 const GValue *value,
1046 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1050 lightdm_greeter_get_property (GObject *object,
1055 LightDMGreeter *self;
1057 self = LIGHTDM_GREETER (object);
1060 case PROP_DEFAULT_SESSION_HINT:
1061 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1063 case PROP_HIDE_USERS_HINT:
1064 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1066 case PROP_SHOW_MANUAL_LOGIN_HINT:
1067 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1069 case PROP_LOCK_HINT:
1070 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1072 case PROP_HAS_GUEST_ACCOUNT_HINT:
1073 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1075 case PROP_SELECT_USER_HINT:
1076 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1078 case PROP_SELECT_GUEST_HINT:
1079 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1081 case PROP_AUTOLOGIN_USER_HINT:
1082 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1084 case PROP_AUTOLOGIN_GUEST_HINT:
1085 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1087 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1088 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1090 case PROP_AUTHENTICATION_USER:
1091 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1093 case PROP_IN_AUTHENTICATION:
1094 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1096 case PROP_IS_AUTHENTICATED:
1097 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1100 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1106 marshal_VOID__STRING_INT (GClosure *closure,
1107 GValue *return_value G_GNUC_UNUSED,
1108 guint n_param_values,
1109 const GValue *param_values,
1110 gpointer invocation_hint G_GNUC_UNUSED,
1111 gpointer marshal_data)
1113 typedef void (*GMarshalFunc_VOID__STRING_INT) (gpointer data1,
1117 register GMarshalFunc_VOID__STRING_INT callback;
1118 register GCClosure *cc = (GCClosure*) closure;
1119 register gpointer data1, data2;
1121 g_return_if_fail (n_param_values == 3);
1123 if (G_CCLOSURE_SWAP_DATA (closure))
1125 data1 = closure->data;
1126 data2 = g_value_peek_pointer (param_values + 0);
1130 data1 = g_value_peek_pointer (param_values + 0);
1131 data2 = closure->data;
1133 callback = (GMarshalFunc_VOID__STRING_INT) (marshal_data ? marshal_data : cc->callback);
1136 (param_values + 1)->data[0].v_pointer,
1137 (param_values + 2)->data[0].v_int,
1142 lightdm_greeter_finalize (GObject *object)
1144 LightDMGreeter *self = LIGHTDM_GREETER (object);
1145 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1147 if (priv->to_server_channel)
1148 g_io_channel_unref (priv->to_server_channel);
1149 if (priv->from_server_channel)
1150 g_io_channel_unref (priv->from_server_channel);
1151 g_free (priv->authentication_user);
1152 g_hash_table_unref (priv->hints);
1154 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1158 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1160 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1162 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1164 object_class->set_property = lightdm_greeter_set_property;
1165 object_class->get_property = lightdm_greeter_get_property;
1166 object_class->finalize = lightdm_greeter_finalize;
1168 g_object_class_install_property (object_class,
1169 PROP_DEFAULT_SESSION_HINT,
1170 g_param_spec_string ("default-session-hint",
1171 "default-session-hint",
1172 "Default session hint",
1174 G_PARAM_READWRITE));
1176 g_object_class_install_property (object_class,
1177 PROP_HIDE_USERS_HINT,
1178 g_param_spec_boolean ("hide-users-hint",
1184 g_object_class_install_property (object_class,
1185 PROP_SHOW_MANUAL_LOGIN_HINT,
1186 g_param_spec_boolean ("show-manual-login-hint",
1187 "show-manual-login-hint",
1188 "Show manual login hint",
1192 g_object_class_install_property (object_class,
1194 g_param_spec_boolean ("lock-hint",
1200 g_object_class_install_property (object_class,
1201 PROP_HAS_GUEST_ACCOUNT_HINT,
1202 g_param_spec_boolean ("has-guest-account-hint",
1203 "has-guest-account-hint",
1204 "Has guest account hint",
1208 g_object_class_install_property (object_class,
1209 PROP_SELECT_USER_HINT,
1210 g_param_spec_string ("select-user-hint",
1216 g_object_class_install_property (object_class,
1217 PROP_SELECT_GUEST_HINT,
1218 g_param_spec_boolean ("select-guest-hint",
1219 "select-guest-hint",
1220 "Select guest account hint",
1224 g_object_class_install_property (object_class,
1225 PROP_AUTOLOGIN_USER_HINT,
1226 g_param_spec_string ("autologin-user-hint",
1227 "autologin-user-hint",
1228 "Autologin user hint",
1232 g_object_class_install_property (object_class,
1233 PROP_AUTOLOGIN_GUEST_HINT,
1234 g_param_spec_boolean ("autologin-guest-hint",
1235 "autologin-guest-hint",
1236 "Autologin guest account hint",
1240 g_object_class_install_property (object_class,
1241 PROP_AUTOLOGIN_TIMEOUT_HINT,
1242 g_param_spec_int ("autologin-timeout-hint",
1243 "autologin-timeout-hint",
1244 "Autologin timeout hint",
1248 g_object_class_install_property (object_class,
1249 PROP_AUTHENTICATION_USER,
1250 g_param_spec_string ("authentication-user",
1251 "authentication-user",
1252 "The user being authenticated",
1255 g_object_class_install_property (object_class,
1256 PROP_IN_AUTHENTICATION,
1257 g_param_spec_boolean ("in-authentication",
1258 "in-authentication",
1259 "TRUE if a user is being authenticated",
1262 g_object_class_install_property (object_class,
1263 PROP_IS_AUTHENTICATED,
1264 g_param_spec_boolean ("is-authenticated",
1266 "TRUE if the selected user is authenticated",
1271 * LightDMGreeter::show-prompt:
1272 * @greeter: A #LightDMGreeter
1273 * @text: Prompt text
1274 * @type: Prompt type
1276 * The ::show-prompt signal gets emitted when the greeter should show a
1277 * prompt to the user. The given text should be displayed and an input
1278 * field for the user to provide a response.
1280 * Call lightdm_greeter_respond() with the resultant input or
1281 * lightdm_greeter_cancel_authentication() to abort the authentication.
1283 signals[SHOW_PROMPT] =
1284 g_signal_new ("show-prompt",
1285 G_TYPE_FROM_CLASS (klass),
1287 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1289 marshal_VOID__STRING_INT,
1290 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1293 * LightDMGreeter::show-message:
1294 * @greeter: A #LightDMGreeter
1295 * @text: Message text
1296 * @type: Message type
1298 * The ::show-message signal gets emitted when the greeter
1299 * should show a message to the user.
1301 signals[SHOW_MESSAGE] =
1302 g_signal_new ("show-message",
1303 G_TYPE_FROM_CLASS (klass),
1305 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1307 marshal_VOID__STRING_INT,
1308 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1311 * LightDMGreeter::authentication-complete:
1312 * @greeter: A #LightDMGreeter
1314 * The ::authentication-complete signal gets emitted when the greeter
1315 * has completed authentication.
1317 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1320 signals[AUTHENTICATION_COMPLETE] =
1321 g_signal_new ("authentication-complete",
1322 G_TYPE_FROM_CLASS (klass),
1324 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1326 g_cclosure_marshal_VOID__VOID,
1330 * LightDMGreeter::autologin-timer-expired:
1331 * @greeter: A #LightDMGreeter
1333 * The ::timed-login signal gets emitted when the automatic login timer has expired.
1334 * The application should then call lightdm_greeter_login().
1336 signals[AUTOLOGIN_TIMER_EXPIRED] =
1337 g_signal_new ("autologin-timer-expired",
1338 G_TYPE_FROM_CLASS (klass),
1340 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1342 g_cclosure_marshal_VOID__VOID,