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