]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/greeter.c
Use a session type for different types of sessions
[sojka/lightdm.git] / liblightdm-gobject / greeter.c
1 /*
2  * Copyright (C) 2010 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  *
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.
9  */
10
11 #include <config.h>
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <security/pam_appl.h>
16
17 #include "lightdm/greeter.h"
18
19 enum {
20     PROP_0,
21     PROP_DEFAULT_SESSION_HINT,
22     PROP_HIDE_USERS_HINT,
23     PROP_SHOW_MANUAL_LOGIN_HINT,
24     PROP_SHOW_REMOTE_LOGIN_HINT,
25     PROP_LOCK_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,
35 };
36
37 enum {
38     SHOW_PROMPT,
39     SHOW_MESSAGE,
40     AUTHENTICATION_COMPLETE,
41     AUTOLOGIN_TIMER_EXPIRED,
42     LAST_SIGNAL
43 };
44 static guint signals[LAST_SIGNAL] = { 0 };
45
46 typedef struct
47 {
48     gboolean connected;
49
50     GIOChannel *to_server_channel, *from_server_channel;
51     guint8 *read_buffer;
52     gsize n_read;
53
54     gsize n_responses_waiting;
55     GList *responses_received;
56
57     GHashTable *hints;
58     guint autologin_timeout;
59
60     gchar *authentication_user;
61     gboolean in_authentication;
62     gboolean is_authenticated;
63     guint32 authenticate_sequence_number;
64     gboolean cancelling_authentication;
65 } LightDMGreeterPrivate;
66
67 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
68
69 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
70
71 #define HEADER_SIZE 8
72 #define MAX_MESSAGE_LENGTH 1024
73
74 /* Messages from the greeter to the server */
75 typedef enum
76 {
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,
84     GREETER_MESSAGE_AUTHENTICATE_REMOTE
85 } GreeterMessage;
86
87 /* Messages from the server to the greeter */
88 typedef enum
89 {
90     SERVER_MESSAGE_CONNECTED = 0,
91     SERVER_MESSAGE_PROMPT_AUTHENTICATION,
92     SERVER_MESSAGE_END_AUTHENTICATION,
93     SERVER_MESSAGE_SESSION_RESULT
94 } ServerMessage;
95
96 /**
97  * lightdm_greeter_new:
98  *
99  * Create a new greeter.
100  *
101  * Return value: the new #LightDMGreeter
102  **/
103 LightDMGreeter *
104 lightdm_greeter_new ()
105 {
106     return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
107 }
108
109 static gboolean
110 timed_login_cb (gpointer data)
111 {
112     LightDMGreeter *greeter = data;
113     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
114
115     priv->autologin_timeout = 0;
116     g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
117
118     return FALSE;
119 }
120
121 static guint32
122 int_length (void)
123 {
124     return 4;
125 }
126
127 static void
128 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
129 {
130     if (*offset + 4 >= buffer_length)
131         return;
132     buffer[*offset] = value >> 24;
133     buffer[*offset+1] = (value >> 16) & 0xFF;
134     buffer[*offset+2] = (value >> 8) & 0xFF;
135     buffer[*offset+3] = value & 0xFF;
136     *offset += 4;
137 }
138
139 static void
140 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
141 {
142     gint length = 0;
143
144     if (value)
145         length = strlen (value);
146     write_int (buffer, buffer_length, length, offset);
147     if (*offset + length >= buffer_length)
148         return;
149     memcpy (buffer + *offset, value, length);
150     *offset += length;
151 }
152
153 static guint32
154 read_int (guint8 *message, gsize message_length, gsize *offset)
155 {
156     guint32 value;
157     guint8 *buffer;
158
159     if (message_length - *offset < int_length ())
160     {
161         g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
162         return 0;
163     }
164
165     buffer = message + *offset;
166     value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
167     *offset += int_length ();
168
169     return value;
170 }
171
172 static gchar *
173 read_string (guint8 *message, gsize message_length, gsize *offset)
174 {
175     guint32 length;
176     gchar *value;
177
178     length = read_int (message, message_length, offset);
179     if (message_length - *offset < length)
180     {
181         g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
182         return g_strdup ("");
183     }
184
185     value = g_malloc (sizeof (gchar) * (length + 1));
186     memcpy (value, message + *offset, length);
187     value[length] = '\0';
188     *offset += length;
189
190     return value;
191 }
192
193 static guint32
194 string_length (const gchar *value)
195 {
196     if (value)
197         return int_length () + strlen (value);
198     else
199         return int_length ();
200 }
201
202 static void
203 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
204 {
205     write_int (buffer, buffer_length, id, offset);
206     write_int (buffer, buffer_length, length, offset);
207 }
208
209 static guint32
210 get_message_length (guint8 *message, gsize message_length)
211 {
212     gsize offset = 4;
213     return read_int (message, message_length, &offset);
214 }
215
216 static void
217 write_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
218 {
219     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
220     GIOStatus status;
221     GError *error = NULL;
222     guint32 stated_length;
223
224     /* Double check that we're sending well-formed messages.  If we say we're
225        sending more than we do, we end up DOS'ing lightdm as it waits for the
226        rest.  If we say we're sending less than we do, we confuse the heck out
227        of lightdm, as it starts reading headers from the middle of our
228        messages. */
229     stated_length = HEADER_SIZE + get_message_length (message, message_length);
230     if (stated_length != message_length)
231     {
232         g_warning ("Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu", stated_length, message_length);
233         return;
234     }
235
236     status = g_io_channel_write_chars (priv->to_server_channel, (gchar *) message, message_length, NULL, &error);
237     if (error)
238         g_warning ("Error writing to daemon: %s", error->message);
239     g_clear_error (&error);
240     if (status == G_IO_STATUS_NORMAL)
241         g_debug ("Wrote %zi bytes to daemon", message_length);
242     g_io_channel_flush (priv->to_server_channel, NULL);
243 }
244
245 static void
246 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
247 {
248     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
249     gchar *version;
250     GString *hint_string;
251     int timeout;
252
253     version = read_string (message, message_length, offset);
254     hint_string = g_string_new ("");
255     while (*offset < message_length)
256     {
257         gchar *name, *value;
258       
259         name = read_string (message, message_length, offset);
260         value = read_string (message, message_length, offset);
261         g_hash_table_insert (priv->hints, name, value);
262         g_string_append_printf (hint_string, " %s=%s", name, value);
263     }
264
265     g_debug ("Connected version=%s%s", version, hint_string->str);
266     g_free (version);
267     g_string_free (hint_string, TRUE);
268
269     /* Set timeout for default login */
270     timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
271     if (timeout)
272     {
273         g_debug ("Setting autologin timer for %d seconds", timeout);
274         priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
275     }
276 }
277
278 static void
279 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
280 {
281     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
282     guint32 sequence_number, n_messages, i;
283     gchar *username;
284
285     sequence_number = read_int (message, message_length, offset);
286     if (sequence_number != priv->authenticate_sequence_number)
287     {
288         g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
289         return;
290     }
291
292     if (priv->cancelling_authentication)
293     {
294         g_debug ("Ignoring prompt authentication as waiting for it to cancel");
295         return;
296     }
297
298     /* Update username */
299     username = read_string (message, message_length, offset);
300     if (strcmp (username, "") == 0)
301     {
302         g_free (username);
303         username = NULL;
304     }
305     g_free (priv->authentication_user);
306     priv->authentication_user = username;
307
308     g_list_free_full (priv->responses_received, g_free);
309     priv->responses_received = NULL;
310     priv->n_responses_waiting = 0;
311
312     n_messages = read_int (message, message_length, offset);
313     g_debug ("Prompt user with %d message(s)", n_messages);
314
315     for (i = 0; i < n_messages; i++)
316     {
317         int style;
318         gchar *text;
319
320         style = read_int (message, message_length, offset);
321         text = read_string (message, message_length, offset);
322
323         // FIXME: Should stop on prompts?
324         switch (style)
325         {
326         case PAM_PROMPT_ECHO_OFF:
327             priv->n_responses_waiting++;
328             g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
329             break;
330         case PAM_PROMPT_ECHO_ON:
331             priv->n_responses_waiting++;
332             g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
333             break;
334         case PAM_ERROR_MSG:
335             g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
336             break;
337         case PAM_TEXT_INFO:
338             g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
339             break;
340         }
341
342         g_free (text);
343     }
344 }
345
346 static void
347 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
348 {
349     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
350     guint32 sequence_number, return_code;
351     gchar *username;
352
353     sequence_number = read_int (message, message_length, offset);
354
355     if (sequence_number != priv->authenticate_sequence_number)
356     {
357         g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
358         return;
359     }
360
361     username = read_string (message, message_length, offset);
362     return_code = read_int (message, message_length, offset);
363
364     g_debug ("Authentication complete for user %s with return code %d", username, return_code);
365
366     /* Update username */
367     if (strcmp (username, "") == 0)
368     {
369         g_free (username);
370         username = NULL;
371     }
372     g_free (priv->authentication_user);
373     priv->authentication_user = username;
374
375     priv->cancelling_authentication = FALSE;
376     priv->is_authenticated = (return_code == 0);
377
378     priv->in_authentication = FALSE;
379     g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
380 }
381
382 static guint8 *
383 read_message (LightDMGreeter *greeter, gsize *length, gboolean block)
384 {
385     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
386     gsize n_to_read, n_read;
387     guint8 *buffer;
388     GError *error = NULL;
389
390     /* Read the header, or the whole message if we already have that */
391     n_to_read = HEADER_SIZE;
392     if (priv->n_read >= HEADER_SIZE)
393         n_to_read += get_message_length (priv->read_buffer, priv->n_read);
394
395     do
396     {
397         GIOStatus status;
398         status = g_io_channel_read_chars (priv->from_server_channel,
399                                           (gchar *) priv->read_buffer + priv->n_read,
400                                           n_to_read - priv->n_read,
401                                           &n_read,
402                                           &error);
403         if (error)
404             g_warning ("Error reading from server: %s", error->message);
405         g_clear_error (&error);
406         if (status != G_IO_STATUS_NORMAL)
407             break;
408
409         g_debug ("Read %zi bytes from daemon", n_read);
410
411         priv->n_read += n_read;
412     } while (priv->n_read < n_to_read && block);
413
414     /* Stop if haven't got all the data we want */
415     if (priv->n_read != n_to_read)
416         return FALSE;
417
418     /* If have header, rerun for content */
419     if (priv->n_read == HEADER_SIZE)
420     {
421         n_to_read = get_message_length (priv->read_buffer, priv->n_read);
422         if (n_to_read > 0)
423         {
424             priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
425             return read_message (greeter, length, block);
426         }
427     }
428
429     buffer = priv->read_buffer;
430     *length = priv->n_read;
431
432     priv->read_buffer = g_malloc (priv->n_read);
433     priv->n_read = 0;
434
435     return buffer;
436 }
437
438 static gboolean
439 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
440 {
441     LightDMGreeter *greeter = data;
442     guint8 *message;
443     gsize message_length, offset;
444     guint32 id;
445
446     message = read_message (greeter, &message_length, FALSE);
447     if (!message)
448         return TRUE;
449
450     offset = 0;
451     id = read_int (message, message_length, &offset);
452     read_int (message, message_length, &offset);
453     switch (id)
454     {
455     case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
456         handle_prompt_authentication (greeter, message, message_length, &offset);
457         break;
458     case SERVER_MESSAGE_END_AUTHENTICATION:
459         handle_end_authentication (greeter, message, message_length, &offset);
460         break;
461     default:
462         g_warning ("Unknown message from server: %d", id);
463         break;
464     }
465     g_free (message);
466
467     return TRUE;
468 }
469
470 /**
471  * lightdm_greeter_connect_sync:
472  * @greeter: The greeter to connect
473  * @error: return location for a #GError, or %NULL
474  *
475  * Connects the greeter to the display manager.  Will block until connected.
476  *
477  * Return value: #TRUE if successfully connected
478  **/
479 gboolean
480 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
481 {
482     LightDMGreeterPrivate *priv;
483     const gchar *fd;
484     guint8 message[MAX_MESSAGE_LENGTH];
485     guint8 *response;
486     gsize response_length, offset = 0;
487     guint32 id;
488
489     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
490
491     priv = GET_PRIVATE (greeter);
492
493     fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
494     if (!fd)
495     {
496         g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
497         return FALSE;
498     }
499     priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
500     g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
501
502     fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
503     if (!fd)
504     {
505         g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
506         return FALSE;
507     }
508     priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
509     g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
510     g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
511
512     g_debug ("Connecting to display manager...");
513     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION), &offset);
514     write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
515     write_message (greeter, message, offset);
516
517     response = read_message (greeter, &response_length, TRUE);
518     if (!response)
519         return FALSE;
520
521     offset = 0;
522     id = read_int (response, response_length, &offset);
523     read_int (response, response_length, &offset);
524     if (id == SERVER_MESSAGE_CONNECTED)
525         handle_connected (greeter, response, response_length, &offset);
526     g_free (response);
527     if (id != SERVER_MESSAGE_CONNECTED)
528     {
529         g_warning ("Expected CONNECTED message, got %d", id);
530         return FALSE;
531     }
532
533     priv->connected = TRUE;
534
535     return TRUE;
536 }
537
538 /**
539  * lightdm_greeter_get_hint:
540  * @greeter: A #LightDMGreeter
541  * @name: The hint name to query.
542  *
543  * Get a hint.
544  *
545  * Return value: The value for this hint or #NULL if not set.
546  **/
547 const gchar *
548 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
549 {
550     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
551     return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
552 }
553
554 /**
555  * lightdm_greeter_get_default_session_hint:
556  * @greeter: A #LightDMGreeter
557  *
558  * Get the default session to use.
559  *
560  * Return value: The session name
561  **/
562 const gchar *
563 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
564 {
565     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
566     return lightdm_greeter_get_hint (greeter, "default-session");
567 }
568
569 /**
570  * lightdm_greeter_get_hide_users_hint:
571  * @greeter: A #LightDMGreeter
572  *
573  * Check if user accounts should be shown.  If this is TRUE then the list of
574  * accounts should be taken from #LightDMUserList and displayed in the greeter
575  * for the user to choose from.  Note that this list can be empty and it is
576  * recommended you show a method for the user to enter a username manually.
577  * 
578  * If this option is shown the greeter should only allow these users to be
579  * chosen for login unless the manual login hint is set.
580  *
581  * Return value: #TRUE if the available users should not be shown.
582  */
583 gboolean
584 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
585 {
586     const gchar *value;
587
588     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
589     value = lightdm_greeter_get_hint (greeter, "hide-users");
590
591     return g_strcmp0 (value, "true") == 0;
592 }
593
594 /**
595  * lightdm_greeter_get_show_manual_login_hint:
596  * @greeter: A #LightDMGreeter
597  *
598  * Check if a manual login option should be shown.  If set the GUI
599  * should provide a way for a username to be entered manually.
600  * Without this hint a greeter which is showing a user list can
601  * limit logins to only those users.
602  *
603  * Return value: #TRUE if a manual login option should be shown.
604  */
605 gboolean
606 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
607 {
608     const gchar *value;
609
610     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
611     value = lightdm_greeter_get_hint (greeter, "show-manual-login");
612
613     return g_strcmp0 (value, "true") == 0;
614 }
615
616 /**
617  * lightdm_greeter_get_show_remote_login_hint:
618  * @greeter: A #LightDMGreeter
619  *
620  * Check if a remote login option should be shown.  If set the GUI
621  * should provide a way for a user to log into a remote desktop server.
622  *
623  * Return value: #TRUE if a remote login option should be shown.
624  */
625 gboolean
626 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
627 {
628     const gchar *value;
629
630     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
631     value = lightdm_greeter_get_hint (greeter, "show-remote-login");
632
633     return g_strcmp0 (value, "true") == 0;
634 }
635
636 /**
637  * lightdm_greeter_get_lock_hint:
638  * @greeter: A #LightDMGreeter
639  *
640  * Check if the greeter is acting as a lock screen.
641  *
642  * Return value: #TRUE if the greeter was triggered by locking the seat.
643  */
644 gboolean
645 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
646 {
647     const gchar *value;
648
649     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
650     value = lightdm_greeter_get_hint (greeter, "lock-screen");
651
652     return g_strcmp0 (value, "true") == 0;
653 }
654
655 /**
656  * lightdm_greeter_get_has_guest_account_hint:
657  * @greeter: A #LightDMGreeter
658  *
659  * Check if guest sessions are supported.
660  *
661  * Return value: #TRUE if guest sessions are supported.
662  */
663 gboolean
664 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
665 {
666     const gchar *value;
667
668     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
669     value = lightdm_greeter_get_hint (greeter, "has-guest-account");
670   
671     return g_strcmp0 (value, "true") == 0;
672 }
673
674 /**
675  * lightdm_greeter_get_select_user_hint:
676  * @greeter: A #LightDMGreeter
677  *
678  * Get the user to select by default.
679  *
680  * Return value: A username
681  */
682 const gchar *
683 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
684 {
685     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
686     return lightdm_greeter_get_hint (greeter, "select-user");
687 }
688
689 /**
690  * lightdm_greeter_get_select_guest_hint:
691  * @greeter: A #LightDMGreeter
692  *
693  * Check if the guest account should be selected by default.
694  *
695  * Return value: #TRUE if the guest account should be selected by default.
696  */
697 gboolean
698 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
699 {
700     const gchar *value;
701
702     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
703     value = lightdm_greeter_get_hint (greeter, "select-guest");
704   
705     return g_strcmp0 (value, "true") == 0;
706 }
707
708 /**
709  * lightdm_greeter_get_autologin_user_hint:
710  * @greeter: A #LightDMGreeter
711  *
712  * Get the user account to automatically logg into when the timer expires.
713  *
714  * Return value: The user account to automatically log into.
715  */
716 const gchar *
717 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
718 {
719     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
720     return lightdm_greeter_get_hint (greeter, "autologin-user");
721 }
722
723 /**
724  * lightdm_greeter_get_autologin_guest_hint:
725  * @greeter: A #LightDMGreeter
726  *
727  * Check if the guest account should be automatically logged into when the timer expires.
728  *
729  * Return value: #TRUE if the guest account should be automatically logged into.
730  */
731 gboolean
732 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
733 {
734     const gchar *value;
735
736     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
737     value = lightdm_greeter_get_hint (greeter, "autologin-guest");
738   
739     return g_strcmp0 (value, "true") == 0;
740 }
741
742 /**
743  * lightdm_greeter_get_autologin_timeout_hint:
744  * @greeter: A #LightDMGreeter
745  *
746  * Get the number of seconds to wait before automaitcally logging in.
747  *
748  * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
749  */
750 gint
751 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
752 {
753     const gchar *value;
754     gint timeout = 0;
755
756     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
757     value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
758     if (value)
759         timeout = atoi (value);
760     if (timeout < 0)
761         timeout = 0;
762
763     return timeout;
764 }
765
766 /**
767  * lightdm_greeter_cancel_autologin:
768  * @greeter: A #LightDMGreeter
769  *
770  * Cancel the automatic login.
771  */
772 void
773 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
774 {
775     LightDMGreeterPrivate *priv;
776
777     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
778
779     priv = GET_PRIVATE (greeter);
780
781     if (priv->autologin_timeout)
782        g_source_remove (priv->autologin_timeout);
783     priv->autologin_timeout = 0;
784 }
785
786 /**
787  * lightdm_greeter_authenticate:
788  * @greeter: A #LightDMGreeter
789  * @username: (allow-none): A username or #NULL to prompt for a username.
790  *
791  * Starts the authentication procedure for a user.
792  **/
793 void
794 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
795 {
796     LightDMGreeterPrivate *priv;
797     guint8 message[MAX_MESSAGE_LENGTH];
798     gsize offset = 0;
799
800     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
801
802     priv = GET_PRIVATE (greeter);
803
804     g_return_if_fail (priv->connected);
805
806     priv->cancelling_authentication = FALSE;
807     priv->authenticate_sequence_number++;
808     priv->in_authentication = TRUE;  
809     priv->is_authenticated = FALSE;
810     if (username != priv->authentication_user)
811     {
812         g_free (priv->authentication_user);
813         priv->authentication_user = g_strdup (username);
814     }
815
816     g_debug ("Starting authentication for user %s...", username);
817     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
818     write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
819     write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
820     write_message (greeter, message, offset);
821 }
822
823 /**
824  * lightdm_greeter_authenticate_as_guest:
825  * @greeter: A #LightDMGreeter
826  *
827  * Starts the authentication procedure for the guest user.
828  **/
829 void
830 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
831 {
832     LightDMGreeterPrivate *priv;
833     guint8 message[MAX_MESSAGE_LENGTH];
834     gsize offset = 0;
835
836     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
837
838     priv = GET_PRIVATE (greeter);
839
840     g_return_if_fail (priv->connected);
841
842     priv->cancelling_authentication = FALSE;
843     priv->authenticate_sequence_number++;
844     priv->in_authentication = TRUE;
845     priv->is_authenticated = FALSE;
846     g_free (priv->authentication_user);
847     priv->authentication_user = NULL;
848
849     g_debug ("Starting authentication for guest account...");
850     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
851     write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
852     write_message (greeter, message, offset);
853 }
854
855 /**
856  * lightdm_greeter_authenticate_autologin:
857  * @greeter: A #LightDMGreeter
858  *
859  * Starts the authentication procedure for the automatic login user.
860  **/
861 void
862 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
863 {
864     const gchar *user;
865
866     user = lightdm_greeter_get_autologin_user_hint (greeter);
867     if (lightdm_greeter_get_autologin_guest_hint (greeter))
868         lightdm_greeter_authenticate_as_guest (greeter);
869     else if (user)
870         lightdm_greeter_authenticate (greeter, user);
871 }
872
873 /**
874  * lightdm_greeter_authenticate_remote:
875  * @greeter: A #LightDMGreeter
876  * @session: The name of a remote session
877  * @username: (allow-none): A username of #NULL to prompt for a username.
878  *
879  * Start authentication for a remote session type.
880  **/
881 void
882 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
883 {
884     LightDMGreeterPrivate *priv;
885     guint8 message[MAX_MESSAGE_LENGTH];
886     gsize offset = 0;
887
888     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
889
890     priv = GET_PRIVATE (greeter);
891
892     g_return_if_fail (priv->connected);
893
894     priv->cancelling_authentication = FALSE;
895     priv->authenticate_sequence_number++;
896     priv->in_authentication = TRUE;
897     priv->is_authenticated = FALSE;
898     g_free (priv->authentication_user);
899     priv->authentication_user = NULL;
900
901     if (username)
902         g_debug ("Starting authentication for remote session %s as user %s...", session, username);
903     else
904         g_debug ("Starting authentication for remote session %s...", session);
905     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
906     write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
907     write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
908     write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
909     write_message (greeter, message, offset);
910 }
911
912 /**
913  * lightdm_greeter_respond:
914  * @greeter: A #LightDMGreeter
915  * @response: Response to a prompt
916  *
917  * Provide response to a prompt.  May be one in a series.
918  **/
919 void
920 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
921 {
922     LightDMGreeterPrivate *priv;
923     guint8 message[MAX_MESSAGE_LENGTH];
924     gsize offset = 0;
925
926     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
927     g_return_if_fail (response != NULL);
928
929     priv = GET_PRIVATE (greeter);
930
931     g_return_if_fail (priv->connected);
932     g_return_if_fail (priv->n_responses_waiting > 0);
933
934     priv->n_responses_waiting--;
935     priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
936
937     if (priv->n_responses_waiting == 0)
938     {
939       guint32 msg_length;
940       GList *iter;
941
942       g_debug ("Providing response to display manager");
943
944       msg_length = int_length ();
945       for (iter = priv->responses_received; iter; iter = iter->next)
946       {
947           msg_length += string_length ((gchar *)iter->data);
948       }
949
950       write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
951       write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
952       for (iter = priv->responses_received; iter; iter = iter->next)
953       {
954           write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
955       }
956       write_message (greeter, message, offset);
957
958       g_list_free_full (priv->responses_received, g_free);
959       priv->responses_received = NULL;
960     }
961 }
962
963 /**
964  * lightdm_greeter_cancel_authentication:
965  * @greeter: A #LightDMGreeter
966  *
967  * Cancel the current user authentication.
968  **/
969 void
970 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
971 {
972     LightDMGreeterPrivate *priv;
973     guint8 message[MAX_MESSAGE_LENGTH];
974     gsize offset = 0;
975
976     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
977
978     priv = GET_PRIVATE (greeter);
979
980     g_return_if_fail (priv->connected);
981
982     priv->cancelling_authentication = TRUE;
983     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
984     write_message (greeter, message, offset);
985 }
986
987 /**
988  * lightdm_greeter_get_in_authentication:
989  * @greeter: A #LightDMGreeter
990  *
991  * Checks if the greeter is in the process of authenticating.
992  *
993  * Return value: #TRUE if the greeter is authenticating a user.
994  **/
995 gboolean
996 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
997 {
998     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
999     return GET_PRIVATE (greeter)->in_authentication;
1000 }
1001
1002 /**
1003  * lightdm_greeter_get_is_authenticated:
1004  * @greeter: A #LightDMGreeter
1005  *
1006  * Checks if the greeter has successfully authenticated.
1007  *
1008  * Return value: #TRUE if the greeter is authenticated for login.
1009  **/
1010 gboolean
1011 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1012 {
1013     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1014     return GET_PRIVATE (greeter)->is_authenticated;
1015 }
1016
1017 /**
1018  * lightdm_greeter_get_authentication_user:
1019  * @greeter: A #LightDMGreeter
1020  *
1021  * Get the user that is being authenticated.
1022  *
1023  * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
1024  */
1025 const gchar *
1026 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1027 {
1028     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1029     return GET_PRIVATE (greeter)->authentication_user;
1030 }
1031
1032 /**
1033  * lightdm_greeter_set_language:
1034  * @greeter: A #LightDMGreeter
1035  * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1036  *
1037  * Set the language for the currently authenticated user.
1038  **/
1039 void
1040 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
1041 {
1042     LightDMGreeterPrivate *priv;
1043     guint8 message[MAX_MESSAGE_LENGTH];
1044     gsize offset = 0;
1045
1046     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1047
1048     priv = GET_PRIVATE (greeter);
1049
1050     g_return_if_fail (priv->connected);
1051
1052     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
1053     write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
1054     write_message (greeter, message, offset);
1055 }
1056
1057 /**
1058  * lightdm_greeter_start_session_sync:
1059  * @greeter: A #LightDMGreeter
1060  * @session: (allow-none): The session to log into or #NULL to use the default.
1061  * @error: return location for a #GError, or %NULL
1062  *
1063  * Start a session for the authenticated user.
1064  *
1065  * Return value: TRUE if the session was started.
1066  **/
1067 gboolean
1068 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1069 {
1070     LightDMGreeterPrivate *priv;
1071     guint8 message[MAX_MESSAGE_LENGTH];
1072     guint8 *response;
1073     gsize response_length, offset = 0;
1074     guint32 id, return_code = 1;
1075
1076     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1077
1078     priv = GET_PRIVATE (greeter);
1079
1080     g_return_val_if_fail (priv->connected, FALSE);
1081     g_return_val_if_fail (priv->is_authenticated, FALSE);
1082
1083     if (session)
1084         g_debug ("Starting session %s", session);
1085     else
1086         g_debug ("Starting default session");
1087
1088     write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
1089     write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1090     write_message (greeter, message, offset);
1091
1092     response = read_message (greeter, &response_length, TRUE);
1093     if (!response)
1094         return FALSE;
1095
1096     offset = 0;
1097     id = read_int (response, response_length, &offset);
1098     read_int (response, response_length, &offset);
1099     if (id == SERVER_MESSAGE_SESSION_RESULT)
1100         return_code = read_int (response, response_length, &offset);
1101     else
1102         g_warning ("Expected SESSION_RESULT message, got %d", id);
1103
1104     g_free (response);
1105
1106     return return_code == 0;
1107 }
1108
1109 static void
1110 lightdm_greeter_init (LightDMGreeter *greeter)
1111 {
1112     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1113
1114     priv->read_buffer = g_malloc (HEADER_SIZE);
1115     priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1116 }
1117
1118 static void
1119 lightdm_greeter_set_property (GObject      *object,
1120                           guint         prop_id,
1121                           const GValue *value,
1122                           GParamSpec   *pspec)
1123 {
1124     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1125 }
1126
1127 static void
1128 lightdm_greeter_get_property (GObject    *object,
1129                           guint       prop_id,
1130                           GValue     *value,
1131                           GParamSpec *pspec)
1132 {
1133     LightDMGreeter *self;
1134
1135     self = LIGHTDM_GREETER (object);
1136
1137     switch (prop_id) {
1138     case PROP_DEFAULT_SESSION_HINT:
1139         g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1140         break;
1141     case PROP_HIDE_USERS_HINT:
1142         g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1143         break;
1144     case PROP_SHOW_MANUAL_LOGIN_HINT:
1145         g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1146         break;
1147     case PROP_SHOW_REMOTE_LOGIN_HINT:
1148         g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1149         break;
1150     case PROP_LOCK_HINT:
1151         g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1152         break;
1153     case PROP_HAS_GUEST_ACCOUNT_HINT:
1154         g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1155         break;
1156     case PROP_SELECT_USER_HINT:
1157         g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1158         break;
1159     case PROP_SELECT_GUEST_HINT:
1160         g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1161         break;
1162     case PROP_AUTOLOGIN_USER_HINT:
1163         g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1164         break;
1165     case PROP_AUTOLOGIN_GUEST_HINT:
1166         g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1167         break;
1168     case PROP_AUTOLOGIN_TIMEOUT_HINT:
1169         g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1170         break;
1171     case PROP_AUTHENTICATION_USER:
1172         g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1173         break;
1174     case PROP_IN_AUTHENTICATION:
1175         g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1176         break;
1177     case PROP_IS_AUTHENTICATED:
1178         g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1179         break;
1180     default:
1181         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1182         break;
1183     }
1184 }
1185
1186 static void
1187 marshal_VOID__STRING_INT (GClosure     *closure,
1188                           GValue       *return_value G_GNUC_UNUSED,
1189                           guint         n_param_values,
1190                           const GValue *param_values,
1191                           gpointer      invocation_hint G_GNUC_UNUSED,
1192                           gpointer      marshal_data)
1193 {
1194     typedef void (*GMarshalFunc_VOID__STRING_INT) (gpointer     data1,
1195                                                    gpointer     arg_1,
1196                                                    gint         arg_2,
1197                                                    gpointer     data2);
1198     register GMarshalFunc_VOID__STRING_INT callback;
1199     register GCClosure *cc = (GCClosure*) closure;
1200     register gpointer data1, data2;
1201
1202     g_return_if_fail (n_param_values == 3);
1203
1204     if (G_CCLOSURE_SWAP_DATA (closure))
1205     {
1206         data1 = closure->data;
1207         data2 = g_value_peek_pointer (param_values + 0);
1208     }
1209     else
1210     {
1211         data1 = g_value_peek_pointer (param_values + 0);
1212         data2 = closure->data;
1213     }
1214     callback = (GMarshalFunc_VOID__STRING_INT) (marshal_data ? marshal_data : cc->callback);
1215
1216     callback (data1,
1217               (param_values + 1)->data[0].v_pointer,
1218               (param_values + 2)->data[0].v_int,
1219               data2);
1220 }
1221
1222 static void
1223 lightdm_greeter_finalize (GObject *object)
1224 {
1225     LightDMGreeter *self = LIGHTDM_GREETER (object);
1226     LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1227
1228     if (priv->to_server_channel)
1229         g_io_channel_unref (priv->to_server_channel);
1230     if (priv->from_server_channel)
1231         g_io_channel_unref (priv->from_server_channel);
1232     g_free (priv->authentication_user);
1233     g_hash_table_unref (priv->hints);
1234
1235     G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1236 }
1237
1238 static void
1239 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1240 {
1241     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1242
1243     g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1244
1245     object_class->set_property = lightdm_greeter_set_property;
1246     object_class->get_property = lightdm_greeter_get_property;
1247     object_class->finalize = lightdm_greeter_finalize;
1248
1249     g_object_class_install_property (object_class,
1250                                      PROP_DEFAULT_SESSION_HINT,
1251                                      g_param_spec_string ("default-session-hint",
1252                                                           "default-session-hint",
1253                                                           "Default session hint",
1254                                                           NULL,
1255                                                           G_PARAM_READWRITE));
1256
1257     g_object_class_install_property (object_class,
1258                                      PROP_HIDE_USERS_HINT,
1259                                      g_param_spec_boolean ("hide-users-hint",
1260                                                            "hide-users-hint",
1261                                                            "Hide users hint",
1262                                                            FALSE,
1263                                                            G_PARAM_READABLE));
1264
1265     g_object_class_install_property (object_class,
1266                                      PROP_SHOW_MANUAL_LOGIN_HINT,
1267                                      g_param_spec_boolean ("show-manual-login-hint",
1268                                                            "show-manual-login-hint",
1269                                                            "Show manual login hint",
1270                                                            FALSE,
1271                                                            G_PARAM_READABLE));
1272
1273     g_object_class_install_property (object_class,
1274                                      PROP_SHOW_REMOTE_LOGIN_HINT,
1275                                      g_param_spec_boolean ("show-remote-login-hint",
1276                                                            "show-remote-login-hint",
1277                                                            "Show remote login hint",
1278                                                            FALSE,
1279                                                            G_PARAM_READABLE));
1280
1281     g_object_class_install_property (object_class,
1282                                      PROP_LOCK_HINT,
1283                                      g_param_spec_boolean ("lock-hint",
1284                                                            "lock-hint",
1285                                                            "Lock hint",
1286                                                            FALSE,
1287                                                            G_PARAM_READABLE));
1288
1289     g_object_class_install_property (object_class,
1290                                      PROP_HAS_GUEST_ACCOUNT_HINT,
1291                                      g_param_spec_boolean ("has-guest-account-hint",
1292                                                            "has-guest-account-hint",
1293                                                            "Has guest account hint",
1294                                                            FALSE,
1295                                                            G_PARAM_READABLE));
1296
1297     g_object_class_install_property (object_class,
1298                                      PROP_SELECT_USER_HINT,
1299                                      g_param_spec_string ("select-user-hint",
1300                                                           "select-user-hint",
1301                                                           "Select user hint",
1302                                                           NULL,
1303                                                           G_PARAM_READABLE));
1304
1305     g_object_class_install_property (object_class,
1306                                      PROP_SELECT_GUEST_HINT,
1307                                      g_param_spec_boolean ("select-guest-hint",
1308                                                            "select-guest-hint",
1309                                                            "Select guest account hint",
1310                                                            FALSE,
1311                                                            G_PARAM_READABLE));
1312
1313     g_object_class_install_property (object_class,
1314                                      PROP_AUTOLOGIN_USER_HINT,
1315                                      g_param_spec_string ("autologin-user-hint",
1316                                                           "autologin-user-hint",
1317                                                           "Autologin user hint",
1318                                                           NULL,
1319                                                           G_PARAM_READABLE));
1320
1321     g_object_class_install_property (object_class,
1322                                      PROP_AUTOLOGIN_GUEST_HINT,
1323                                      g_param_spec_boolean ("autologin-guest-hint",
1324                                                            "autologin-guest-hint",
1325                                                            "Autologin guest account hint",
1326                                                            FALSE,
1327                                                            G_PARAM_READABLE));
1328
1329     g_object_class_install_property (object_class,
1330                                      PROP_AUTOLOGIN_TIMEOUT_HINT,
1331                                      g_param_spec_int ("autologin-timeout-hint",
1332                                                        "autologin-timeout-hint",
1333                                                        "Autologin timeout hint",
1334                                                        0, G_MAXINT, 0,
1335                                                        G_PARAM_READABLE));
1336
1337     g_object_class_install_property (object_class,
1338                                      PROP_AUTHENTICATION_USER,
1339                                      g_param_spec_string ("authentication-user",
1340                                                           "authentication-user",
1341                                                           "The user being authenticated",
1342                                                           NULL,
1343                                                           G_PARAM_READABLE));
1344     g_object_class_install_property (object_class,
1345                                      PROP_IN_AUTHENTICATION,
1346                                      g_param_spec_boolean ("in-authentication",
1347                                                            "in-authentication",
1348                                                            "TRUE if a user is being authenticated",
1349                                                            FALSE,
1350                                                            G_PARAM_READABLE));
1351     g_object_class_install_property (object_class,
1352                                      PROP_IS_AUTHENTICATED,
1353                                      g_param_spec_boolean ("is-authenticated",
1354                                                            "is-authenticated",
1355                                                            "TRUE if the selected user is authenticated",
1356                                                            FALSE,
1357                                                            G_PARAM_READABLE));
1358
1359     /**
1360      * LightDMGreeter::show-prompt:
1361      * @greeter: A #LightDMGreeter
1362      * @text: Prompt text
1363      * @type: Prompt type
1364      *
1365      * The ::show-prompt signal gets emitted when the greeter should show a
1366      * prompt to the user.  The given text should be displayed and an input
1367      * field for the user to provide a response.
1368      *
1369      * Call lightdm_greeter_respond() with the resultant input or
1370      * lightdm_greeter_cancel_authentication() to abort the authentication.
1371      **/
1372     signals[SHOW_PROMPT] =
1373         g_signal_new ("show-prompt",
1374                       G_TYPE_FROM_CLASS (klass),
1375                       G_SIGNAL_RUN_LAST,
1376                       G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1377                       NULL, NULL,
1378                       marshal_VOID__STRING_INT,
1379                       G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1380
1381     /**
1382      * LightDMGreeter::show-message:
1383      * @greeter: A #LightDMGreeter
1384      * @text: Message text
1385      * @type: Message type
1386      *
1387      * The ::show-message signal gets emitted when the greeter
1388      * should show a message to the user.
1389      **/
1390     signals[SHOW_MESSAGE] =
1391         g_signal_new ("show-message",
1392                       G_TYPE_FROM_CLASS (klass),
1393                       G_SIGNAL_RUN_LAST,
1394                       G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1395                       NULL, NULL,
1396                       marshal_VOID__STRING_INT,
1397                       G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1398
1399     /**
1400      * LightDMGreeter::authentication-complete:
1401      * @greeter: A #LightDMGreeter
1402      *
1403      * The ::authentication-complete signal gets emitted when the greeter
1404      * has completed authentication.
1405      *
1406      * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1407      * was successful.
1408      **/
1409     signals[AUTHENTICATION_COMPLETE] =
1410         g_signal_new ("authentication-complete",
1411                       G_TYPE_FROM_CLASS (klass),
1412                       G_SIGNAL_RUN_LAST,
1413                       G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1414                       NULL, NULL,
1415                       g_cclosure_marshal_VOID__VOID,
1416                       G_TYPE_NONE, 0);
1417
1418     /**
1419      * LightDMGreeter::autologin-timer-expired:
1420      * @greeter: A #LightDMGreeter
1421      *
1422      * The ::timed-login signal gets emitted when the automatic login timer has expired.
1423      * The application should then call lightdm_greeter_login().
1424      **/
1425     signals[AUTOLOGIN_TIMER_EXPIRED] =
1426         g_signal_new ("autologin-timer-expired",
1427                       G_TYPE_FROM_CLASS (klass),
1428                       G_SIGNAL_RUN_LAST,
1429                       G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1430                       NULL, NULL,
1431                       g_cclosure_marshal_VOID__VOID,
1432                       G_TYPE_NONE, 0);
1433 }