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