]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/greeter.c
Allow greeters to run in-session
[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 <gio/gio.h>
16 #include <gio/gunixsocketaddress.h>
17 #include <security/pam_appl.h>
18
19 #include "lightdm/greeter.h"
20
21 G_DEFINE_QUARK (lightdm_greeter_error, lightdm_greeter_error)
22
23 enum {
24     PROP_0,
25     PROP_DEFAULT_SESSION_HINT,
26     PROP_HIDE_USERS_HINT,
27     PROP_SHOW_MANUAL_LOGIN_HINT,
28     PROP_SHOW_REMOTE_LOGIN_HINT,
29     PROP_LOCK_HINT,
30     PROP_HAS_GUEST_ACCOUNT_HINT,
31     PROP_SELECT_USER_HINT,
32     PROP_SELECT_GUEST_HINT,
33     PROP_AUTOLOGIN_USER_HINT,
34     PROP_AUTOLOGIN_GUEST_HINT,
35     PROP_AUTOLOGIN_TIMEOUT_HINT,
36     PROP_AUTHENTICATION_USER,
37     PROP_IN_AUTHENTICATION,
38     PROP_IS_AUTHENTICATED,
39 };
40
41 enum {
42     SHOW_PROMPT,
43     SHOW_MESSAGE,
44     AUTHENTICATION_COMPLETE,
45     AUTOLOGIN_TIMER_EXPIRED,
46     IDLE,
47     RESET,
48     LAST_SIGNAL
49 };
50 static guint signals[LAST_SIGNAL] = { 0 };
51
52 typedef struct
53 {
54     /* TRUE if the daemon can reuse this greeter */
55     gboolean resettable;
56
57     /* Socket connection to daemon */
58     GSocket *socket;
59
60     /* Channel to write to daemon */
61     GIOChannel *to_server_channel;
62
63     /* Channel to read from daemon */
64     GIOChannel *from_server_channel;
65
66     /* Data read from the daemon */
67     guint8 *read_buffer;
68     gsize n_read;
69
70     gsize n_responses_waiting;
71     GList *responses_received;
72
73     /* TRUE if have got a connect response */
74     gboolean connected;
75
76     /* Pending connect requests */
77     GList *connect_requests;
78
79     /* Pending start session requests */
80     GList *start_session_requests;
81
82     /* Pending ensure shared data dir requests */
83     GList *ensure_shared_data_dir_requests;
84
85     /* Hints provided by the daemon */
86     GHashTable *hints;
87
88     /* Timeout source to notify greeter to autologin */
89     guint autologin_timeout;
90
91     gchar *authentication_user;
92     gboolean in_authentication;
93     gboolean is_authenticated;
94     guint32 authenticate_sequence_number;
95     gboolean cancelling_authentication;
96 } LightDMGreeterPrivate;
97
98 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
99
100 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
101
102 #define HEADER_SIZE 8
103 #define MAX_MESSAGE_LENGTH 1024
104
105 /* Messages from the greeter to the server */
106 typedef enum
107 {
108     GREETER_MESSAGE_CONNECT = 0,
109     GREETER_MESSAGE_AUTHENTICATE,
110     GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
111     GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
112     GREETER_MESSAGE_START_SESSION,
113     GREETER_MESSAGE_CANCEL_AUTHENTICATION,
114     GREETER_MESSAGE_SET_LANGUAGE,
115     GREETER_MESSAGE_AUTHENTICATE_REMOTE,
116     GREETER_MESSAGE_ENSURE_SHARED_DIR,
117 } GreeterMessage;
118
119 /* Messages from the server to the greeter */
120 typedef enum
121 {
122     SERVER_MESSAGE_CONNECTED = 0,
123     SERVER_MESSAGE_PROMPT_AUTHENTICATION,
124     SERVER_MESSAGE_END_AUTHENTICATION,
125     SERVER_MESSAGE_SESSION_RESULT,
126     SERVER_MESSAGE_SHARED_DIR_RESULT,
127     SERVER_MESSAGE_IDLE,
128     SERVER_MESSAGE_RESET,
129 } ServerMessage;
130
131 /* Request sent to server */
132 typedef struct
133 {
134     GObject parent_instance;
135     LightDMGreeter *greeter;
136     GCancellable *cancellable;
137     GAsyncReadyCallback callback;
138     gpointer user_data;
139     gboolean complete;
140     gboolean result;
141     GError *error;
142     gchar *dir;
143 } Request;
144 typedef struct
145 {
146     GObjectClass parent_class;
147 } RequestClass;
148 GType request_get_type (void);
149 static void request_iface_init (GAsyncResultIface *iface);
150 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
151 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
152
153 static gboolean from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data);
154
155 GType
156 lightdm_greeter_error_get_type (void)
157 {
158     static GType enum_type = 0;
159
160     if (G_UNLIKELY(enum_type == 0)) {
161         static const GEnumValue values[] = {
162             { LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR, "LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR", "communication-error" },
163             { LIGHTDM_GREETER_ERROR_CONNECTION_FAILED, "LIGHTDM_GREETER_ERROR_CONNECTION_FAILED", "connection-failed" },
164             { LIGHTDM_GREETER_ERROR_SESSION_FAILED, "LIGHTDM_GREETER_ERROR_SESSION_FAILED", "session-failed" },
165             { LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN, "LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN", "no-autologin" },
166             { LIGHTDM_GREETER_ERROR_INVALID_USER, "LIGHTDM_GREETER_ERROR_INVALID_USER", "invalid-user" },          
167             { 0, NULL, NULL }
168         };
169         enum_type = g_enum_register_static (g_intern_static_string ("LightDMGreeterError"), values);
170     }
171
172     return enum_type;
173 }
174
175 GType
176 lightdm_prompt_type_get_type (void)
177 {
178     static GType enum_type = 0;
179   
180     if (G_UNLIKELY(enum_type == 0)) {
181         static const GEnumValue values[] = {
182             { LIGHTDM_PROMPT_TYPE_QUESTION, "LIGHTDM_PROMPT_TYPE_QUESTION", "question" },
183             { LIGHTDM_PROMPT_TYPE_SECRET, "LIGHTDM_PROMPT_TYPE_SECRET", "secret" },
184             { 0, NULL, NULL }
185         };
186         enum_type = g_enum_register_static (g_intern_static_string ("LightDMPromptType"), values);
187     }
188
189     return enum_type;
190 }
191
192 GType
193 lightdm_message_type_get_type (void)
194 {
195     static GType enum_type = 0;
196   
197     if (G_UNLIKELY(enum_type == 0)) {
198         static const GEnumValue values[] = {
199             { LIGHTDM_MESSAGE_TYPE_INFO, "LIGHTDM_MESSAGE_TYPE_INFO", "info" },
200             { LIGHTDM_MESSAGE_TYPE_ERROR, "LIGHTDM_MESSAGE_TYPE_ERROR", "error" },
201             { 0, NULL, NULL }
202         };
203         enum_type = g_enum_register_static (g_intern_static_string ("LightDMMessageType"), values);
204     }
205
206     return enum_type;
207 }
208
209
210 /**
211  * lightdm_greeter_new:
212  *
213  * Create a new greeter.
214  *
215  * Return value: the new #LightDMGreeter
216  **/
217 LightDMGreeter *
218 lightdm_greeter_new (void)
219 {
220     return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
221 }
222
223 /**
224  * lightdm_greeter_set_resettable:
225  * @greeter: A #LightDMGreeter
226  * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
227  *
228  * Set whether the greeter will be reset instead of killed after the user logs in.
229  * This must be called before lightdm_greeter_connect is called.
230  **/
231 void
232 lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
233 {
234     LightDMGreeterPrivate *priv;
235
236     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
237
238     priv = GET_PRIVATE (greeter);
239
240     g_return_if_fail (!priv->connected);
241     priv->resettable = resettable;
242 }
243
244 static Request *
245 request_new (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
246 {
247     Request *request;
248
249     request = g_object_new (request_get_type (), NULL);
250     request->greeter = g_object_ref (greeter);
251     if (cancellable)
252         request->cancellable = g_object_ref (cancellable);
253     request->callback = callback;
254     request->user_data = user_data;
255
256     return request;
257 }
258
259 static gboolean
260 request_callback_cb (gpointer data)
261 {
262     Request *request = data;
263     if (request->callback)
264         request->callback (G_OBJECT (request->greeter), G_ASYNC_RESULT (request), request->user_data);
265     g_object_unref (request);
266     return G_SOURCE_REMOVE;
267 }
268
269 static void
270 request_complete (Request *request)
271 {
272     request->complete = TRUE;
273
274     if (!request->callback)
275         return;
276
277     if (request->cancellable && g_cancellable_is_cancelled (request->cancellable))
278         return;
279
280     g_idle_add (request_callback_cb, g_object_ref (request));
281 }
282
283 static gboolean
284 timed_login_cb (gpointer data)
285 {
286     LightDMGreeter *greeter = data;
287     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
288
289     priv->autologin_timeout = 0;
290     g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
291
292     return FALSE;
293 }
294
295 static guint32
296 int_length (void)
297 {
298     return 4;
299 }
300
301 static gboolean
302 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset, GError **error)
303 {
304     if (*offset + 4 >= buffer_length)
305     {
306         g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
307                              "Not enough buffer space to write integer");
308         return FALSE;
309     }
310     buffer[*offset] = value >> 24;
311     buffer[*offset+1] = (value >> 16) & 0xFF;
312     buffer[*offset+2] = (value >> 8) & 0xFF;
313     buffer[*offset+3] = value & 0xFF;
314     *offset += 4;
315
316     return TRUE;
317 }
318
319 static gboolean
320 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset, GError **error)
321 {
322     gint length = 0;
323
324     if (value)
325         length = strlen (value);
326     if (!write_int (buffer, buffer_length, length, offset, error))
327         return FALSE;
328     if (*offset + length >= buffer_length)
329     {
330         g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
331                      "Not enough buffer space to write string of length %d octets", length);
332         return FALSE;
333     }
334     if (value)
335         memcpy (buffer + *offset, value, length);
336     *offset += length;
337
338     return TRUE;
339 }
340
341 static guint32
342 read_int (guint8 *message, gsize message_length, gsize *offset)
343 {
344     guint32 value;
345     guint8 *buffer;
346
347     if (message_length - *offset < int_length ())
348     {
349         g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
350         return 0;
351     }
352
353     buffer = message + *offset;
354     value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
355     *offset += int_length ();
356
357     return value;
358 }
359
360 static gchar *
361 read_string (guint8 *message, gsize message_length, gsize *offset)
362 {
363     guint32 length;
364     gchar *value;
365
366     length = read_int (message, message_length, offset);
367     if (message_length - *offset < length)
368     {
369         g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
370         return g_strdup ("");
371     }
372
373     value = g_malloc (sizeof (gchar) * (length + 1));
374     memcpy (value, message + *offset, length);
375     value[length] = '\0';
376     *offset += length;
377
378     return value;
379 }
380
381 static guint32
382 string_length (const gchar *value)
383 {
384     if (value)
385         return int_length () + strlen (value);
386     else
387         return int_length ();
388 }
389
390 static gboolean
391 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset, GError **error)
392 {
393     return write_int (buffer, buffer_length, id, offset, error) &&
394            write_int (buffer, buffer_length, length, offset, error);
395 }
396
397 static guint32
398 get_message_length (guint8 *message, gsize message_length)
399 {
400     gsize offset = 4;
401     return read_int (message, message_length, &offset);
402 }
403
404 static gboolean
405 connect_to_daemon (LightDMGreeter *greeter, GError **error)
406 {
407     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
408     const gchar *to_server_fd, *from_server_fd, *pipe_path;
409
410     if (priv->to_server_channel || priv->from_server_channel)
411         return TRUE;
412
413     /* Use private connection if one exists */  
414     to_server_fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
415     from_server_fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
416     pipe_path = g_getenv ("LIGHTDM_GREETER_PIPE");
417     if (to_server_fd && from_server_fd)
418     {
419         priv->to_server_channel = g_io_channel_unix_new (atoi (to_server_fd));
420         priv->from_server_channel = g_io_channel_unix_new (atoi (from_server_fd));
421     }
422     else if (pipe_path)
423     {
424         GSocketAddress *address;
425         gboolean result;
426
427         priv->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error);
428         if (!priv->socket)
429             return FALSE;
430
431         address = g_unix_socket_address_new (pipe_path);
432         result = g_socket_connect (priv->socket, address, NULL, error);
433         g_object_unref (address);
434         if (!result)
435             return FALSE;
436
437         priv->from_server_channel = g_io_channel_unix_new (g_socket_get_fd (priv->socket));
438         priv->to_server_channel = g_io_channel_ref (priv->from_server_channel);
439     }
440     else
441     {
442         g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_CONNECTION_FAILED,
443                              "Unable to determine socket to daemon");
444         return FALSE;
445     }
446
447     g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
448
449     if (!g_io_channel_set_encoding (priv->to_server_channel, NULL, error) ||
450         !g_io_channel_set_encoding (priv->from_server_channel, NULL, error))
451         return FALSE;
452
453     return TRUE;
454 }
455
456 static gboolean
457 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length, GError **error)
458 {
459     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
460     gchar *data;
461     gsize data_length;
462     guint32 stated_length;
463     GError *flush_error = NULL;
464
465     if (!connect_to_daemon (greeter, error))
466         return FALSE;
467
468     /* Double check that we're sending well-formed messages.  If we say we're
469        sending more than we do, we end up DOS'ing lightdm as it waits for the
470        rest.  If we say we're sending less than we do, we confuse the heck out
471        of lightdm, as it starts reading headers from the middle of our
472        messages. */
473     stated_length = HEADER_SIZE + get_message_length (message, message_length);
474     if (stated_length != message_length)
475     {
476         g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
477                      "Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu",
478                      stated_length, message_length);
479         return FALSE;
480     }
481
482     data = (gchar *) message;
483     data_length = message_length;
484     while (data_length > 0)
485     {
486         GIOStatus status;
487         gsize n_written;
488         GError *write_error = NULL;
489
490         status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &write_error);
491         if (write_error)
492             g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
493                          "Failed to write to daemon: %s",
494                          write_error->message);
495         g_clear_error (&write_error);
496         if (status == G_IO_STATUS_AGAIN) 
497             continue;
498         if (status != G_IO_STATUS_NORMAL) 
499             return FALSE;
500         data_length -= n_written;
501         data += n_written;
502     }
503
504     g_debug ("Wrote %zi bytes to daemon", message_length);
505     if (!g_io_channel_flush (priv->to_server_channel, &flush_error))
506     {
507         g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
508                      "Failed to write to daemon: %s",
509                      flush_error->message);
510         g_clear_error (&flush_error);
511         return FALSE;
512     }
513
514     return TRUE;
515 }
516
517 static void
518 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
519 {
520     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
521     gchar *version;
522     GString *hint_string;
523     int timeout;
524     Request *request;
525
526     version = read_string (message, message_length, offset);
527     hint_string = g_string_new ("");
528     while (*offset < message_length)
529     {
530         gchar *name, *value;
531
532         name = read_string (message, message_length, offset);
533         value = read_string (message, message_length, offset);
534         g_hash_table_insert (priv->hints, name, value);
535         g_string_append_printf (hint_string, " %s=%s", name, value);
536     }
537
538     priv->connected = TRUE;
539     g_debug ("Connected version=%s%s", version, hint_string->str);
540     g_free (version);
541     g_string_free (hint_string, TRUE);
542
543     /* Set timeout for default login */
544     timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
545     if (timeout)
546     {
547         g_debug ("Setting autologin timer for %d seconds", timeout);
548         priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
549     }
550
551     /* Notify asynchronous caller */
552     request = g_list_nth_data (priv->connect_requests, 0);
553     if (request)
554     {
555         request->result = TRUE;
556         request_complete (request);
557         priv->connect_requests = g_list_remove (priv->connect_requests, request);
558         g_object_unref (request);
559     }
560 }
561
562 static void
563 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
564 {
565     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
566     guint32 sequence_number, n_messages, i;
567     gchar *username;
568
569     sequence_number = read_int (message, message_length, offset);
570     if (sequence_number != priv->authenticate_sequence_number)
571     {
572         g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
573         return;
574     }
575
576     if (priv->cancelling_authentication)
577     {
578         g_debug ("Ignoring prompt authentication as waiting for it to cancel");
579         return;
580     }
581
582     /* Update username */
583     username = read_string (message, message_length, offset);
584     if (strcmp (username, "") == 0)
585     {
586         g_free (username);
587         username = NULL;
588     }
589     g_free (priv->authentication_user);
590     priv->authentication_user = username;
591
592     g_list_free_full (priv->responses_received, g_free);
593     priv->responses_received = NULL;
594     priv->n_responses_waiting = 0;
595
596     n_messages = read_int (message, message_length, offset);
597     g_debug ("Prompt user with %d message(s)", n_messages);
598
599     for (i = 0; i < n_messages; i++)
600     {
601         int style;
602         gchar *text;
603
604         style = read_int (message, message_length, offset);
605         text = read_string (message, message_length, offset);
606
607         // FIXME: Should stop on prompts?
608         switch (style)
609         {
610         case PAM_PROMPT_ECHO_OFF:
611             priv->n_responses_waiting++;
612             g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
613             break;
614         case PAM_PROMPT_ECHO_ON:
615             priv->n_responses_waiting++;
616             g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
617             break;
618         case PAM_ERROR_MSG:
619             g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
620             break;
621         case PAM_TEXT_INFO:
622             g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
623             break;
624         }
625
626         g_free (text);
627     }
628 }
629
630 static void
631 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
632 {
633     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
634     guint32 sequence_number, return_code;
635     gchar *username;
636
637     sequence_number = read_int (message, message_length, offset);
638
639     if (sequence_number != priv->authenticate_sequence_number)
640     {
641         g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
642         return;
643     }
644
645     username = read_string (message, message_length, offset);
646     return_code = read_int (message, message_length, offset);
647
648     g_debug ("Authentication complete for user %s with return code %d", username, return_code);
649
650     /* Update username */
651     if (strcmp (username, "") == 0)
652     {
653         g_free (username);
654         username = NULL;
655     }
656     g_free (priv->authentication_user);
657     priv->authentication_user = username;
658
659     priv->cancelling_authentication = FALSE;
660     priv->is_authenticated = (return_code == 0);
661
662     priv->in_authentication = FALSE;
663     g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
664 }
665
666 static void
667 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
668 {
669     g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
670 }
671
672 static void
673 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
674 {
675     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
676     GString *hint_string;
677
678     g_hash_table_remove_all (priv->hints);
679
680     hint_string = g_string_new ("");
681     while (*offset < message_length)
682     {
683         gchar *name, *value;
684
685         name = read_string (message, message_length, offset);
686         value = read_string (message, message_length, offset);
687         g_hash_table_insert (priv->hints, name, value);
688         g_string_append_printf (hint_string, " %s=%s", name, value);
689     }
690
691     g_debug ("Reset%s", hint_string->str);
692     g_string_free (hint_string, TRUE);
693
694     g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
695 }
696
697 static void
698 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
699 {
700     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
701     Request *request;
702
703     /* Notify asynchronous caller */
704     request = g_list_nth_data (priv->start_session_requests, 0);
705     if (request)
706     {
707         guint32 return_code;
708
709         return_code = read_int (message, message_length, offset);
710         if (return_code == 0)
711             request->result = TRUE;
712         else
713             request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_SESSION_FAILED,
714                                           "Session returned error code %d", return_code);
715         request_complete (request);
716         priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
717         g_object_unref (request);
718     }
719 }
720
721 static void
722 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
723 {
724     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
725     Request *request;
726
727     /* Notify asynchronous caller */
728     request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
729     if (request)
730     {
731         request->dir = read_string (message, message_length, offset);
732         /* Blank data dir means invalid user */
733         if (g_strcmp0 (request->dir, "") == 0)
734         {
735             g_free (request->dir);
736             request->dir = NULL;
737             request->error = g_error_new (LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_INVALID_USER,
738                                           "No such user");
739         }
740         request_complete (request);
741         priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
742         g_object_unref (request);
743     }
744 }
745
746 static void
747 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
748 {
749     gsize offset = 0;
750     guint32 id;
751
752     id = read_int (message, message_length, &offset);
753     read_int (message, message_length, &offset);
754     switch (id)
755     {
756     case SERVER_MESSAGE_CONNECTED:
757         handle_connected (greeter, message, message_length, &offset);
758         break;
759     case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
760         handle_prompt_authentication (greeter, message, message_length, &offset);
761         break;
762     case SERVER_MESSAGE_END_AUTHENTICATION:
763         handle_end_authentication (greeter, message, message_length, &offset);
764         break;
765     case SERVER_MESSAGE_SESSION_RESULT:
766         handle_session_result (greeter, message, message_length, &offset);
767         break;
768     case SERVER_MESSAGE_SHARED_DIR_RESULT:
769         handle_shared_dir_result (greeter, message, message_length, &offset);
770         break;
771     case SERVER_MESSAGE_IDLE:
772         handle_idle (greeter, message, message_length, &offset);
773         break;
774     case SERVER_MESSAGE_RESET:
775         handle_reset (greeter, message, message_length, &offset);
776         break;
777     default:
778         g_warning ("Unknown message from server: %d", id);
779         break;
780     }
781 }
782
783 static gboolean
784 recv_message (LightDMGreeter *greeter, gboolean block, guint8 **message, gsize *length, GError **error)
785 {
786     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
787     gsize n_to_read, n_read;
788
789     if (!connect_to_daemon (greeter, error))
790         return FALSE;
791
792     /* Read the header, or the whole message if we already have that */
793     n_to_read = HEADER_SIZE;
794     if (priv->n_read >= HEADER_SIZE)
795         n_to_read += get_message_length (priv->read_buffer, priv->n_read);
796
797     do
798     {
799         GIOStatus status;
800         GError *read_error = NULL;
801
802         status = g_io_channel_read_chars (priv->from_server_channel,
803                                           (gchar *) priv->read_buffer + priv->n_read,
804                                           n_to_read - priv->n_read,
805                                           &n_read,
806                                           &read_error);
807         if (status == G_IO_STATUS_AGAIN)
808         {
809             if (block)
810                 continue;
811         }
812         else if (status != G_IO_STATUS_NORMAL)
813         {
814             g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_COMMUNICATION_ERROR,
815                          "Failed to read from daemon: %s",
816                          read_error->message);
817             g_clear_error (&read_error);
818             return FALSE;
819         }
820
821         g_debug ("Read %zi bytes from daemon", n_read);
822
823         priv->n_read += n_read;
824     } while (priv->n_read < n_to_read && block);
825
826     /* Stop if haven't got all the data we want */
827     if (priv->n_read != n_to_read)
828     {
829         if (message)
830             *message = NULL;
831         if (length)
832             *length = 0;
833         return TRUE;
834     }
835
836     /* If have header, rerun for content */
837     if (priv->n_read == HEADER_SIZE)
838     {
839         n_to_read = get_message_length (priv->read_buffer, priv->n_read);
840         if (n_to_read > 0)
841         {
842             priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
843             return recv_message (greeter, block, message, length, error);
844         }
845     }
846
847     if (message)
848         *message = priv->read_buffer;
849     else
850         g_free (priv->read_buffer);
851     if (length)
852         *length = priv->n_read;
853
854     priv->read_buffer = g_malloc (priv->n_read);
855     priv->n_read = 0;
856
857     return TRUE;
858 }
859
860 static gboolean
861 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
862 {
863     LightDMGreeter *greeter = data;
864     guint8 *message;
865     gsize message_length;
866     GError *error = NULL;
867
868     /* Read one message and process it */
869     if (!recv_message (greeter, FALSE, &message, &message_length, &error))
870     {
871         // FIXME: Should push this up to the client somehow
872         g_warning ("Failed to read from daemon: %s\n", error->message);
873         g_clear_error (&error);
874         return G_SOURCE_REMOVE;
875     }
876
877     if (message)
878     {
879         handle_message (greeter, message, message_length);
880         g_free (message);
881     }
882
883     return G_SOURCE_CONTINUE;
884 }
885
886 static gboolean
887 send_connect (LightDMGreeter *greeter, gboolean resettable, GError **error)
888 {
889     guint8 message[MAX_MESSAGE_LENGTH];
890     gsize offset = 0;
891
892     g_debug ("Connecting to display manager...");
893     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset, error) &&
894            write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset, error) &&
895            write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset, error) &&
896            send_message (greeter, message, offset, error);
897 }
898
899 static gboolean
900 send_start_session (LightDMGreeter *greeter, const gchar *session, GError **error)
901 {
902     guint8 message[MAX_MESSAGE_LENGTH];
903     gsize offset = 0;
904
905     if (session)
906         g_debug ("Starting session %s", session);
907     else
908         g_debug ("Starting default session");
909
910     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset, error) &&
911            write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
912            send_message (greeter, message, offset, error);
913 }
914
915 static gboolean
916 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GError **error)
917 {
918     guint8 message[MAX_MESSAGE_LENGTH];
919     gsize offset = 0;
920
921     g_debug ("Ensuring data directory for user %s", username);
922
923     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset, error) &&
924            write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
925            send_message (greeter, message, offset, error);
926 }
927
928 /**
929  * lightdm_greeter_connect_to_daemon:
930  * @greeter: The greeter to connect
931  * @cancellable: (allow-none): A #GCancellable or %NULL.
932  * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
933  * @user_data: (allow-none): data to pass to the @callback or %NULL.
934  *
935  * Asynchronously connects the greeter to the display manager.
936  *
937  * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_to_daemon_finish() to get the result of the operation.
938  *
939  * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
940  **/
941 void
942 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
943 {
944     LightDMGreeterPrivate *priv;
945     Request *request;
946     GError *error = NULL;
947
948     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
949
950     priv = GET_PRIVATE (greeter);
951
952     request = request_new (greeter, cancellable, callback, user_data);
953     if (send_connect (greeter, priv->resettable, &error))
954         priv->connect_requests = g_list_append (priv->connect_requests, request);
955     else
956     {
957         request->error = error;
958         request_complete (request);
959         g_object_unref (request);
960     }
961 }
962
963 /**
964  * lightdm_greeter_connect_to_daemon_finish:
965  * @greeter: The greeter the the request was done with
966  * @result: A #GAsyncResult.
967  * @error: return location for a #GError, or %NULL
968  *
969  * Finishes an operation started with lightdm_greeter_connect_to_daemon().
970  *
971  * Return value: #TRUE if successfully connected
972  **/
973 gboolean
974 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
975 {
976     Request *request = REQUEST (result);
977
978     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
979   
980     g_propagate_error (error, request->error);
981     return request->result;
982 }
983
984 /**
985  * lightdm_greeter_connect_to_daemon_sync:
986  * @greeter: The greeter to connect
987  * @error: return location for a #GError, or %NULL
988  *
989  * Connects the greeter to the display manager.  Will block until connected.
990  *
991  * Return value: #TRUE if successfully connected
992  **/
993 gboolean
994 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
995 {
996     LightDMGreeterPrivate *priv;
997     Request *request;
998
999     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1000
1001     priv = GET_PRIVATE (greeter);
1002
1003     /* Read until we are connected */
1004     if (!send_connect (greeter, priv->resettable, error))
1005         return FALSE;
1006     request = request_new (greeter, NULL, NULL, NULL);
1007     priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
1008     do
1009     {
1010         guint8 *message;
1011         gsize message_length;
1012
1013         if (!recv_message (greeter, TRUE, &message, &message_length, error))
1014             return FALSE;
1015         handle_message (greeter, message, message_length);
1016         g_free (message);
1017     } while (!request->complete);
1018
1019     return lightdm_greeter_connect_to_daemon_finish (greeter, G_ASYNC_RESULT (request), error);
1020 }
1021
1022 /**
1023  * lightdm_greeter_connect_sync:
1024  * @greeter: The greeter to connect
1025  * @error: return location for a #GError, or %NULL
1026  *
1027  * Connects the greeter to the display manager.  Will block until connected.
1028  *
1029  * Return value: #TRUE if successfully connected
1030  *
1031  * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
1032  **/
1033 gboolean
1034 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
1035 {
1036     return lightdm_greeter_connect_to_daemon_sync (greeter, error);
1037 }
1038
1039 /**
1040  * lightdm_greeter_get_hint:
1041  * @greeter: A #LightDMGreeter
1042  * @name: The hint name to query.
1043  *
1044  * Get a hint.
1045  *
1046  * Return value: (nullable): The value for this hint or #NULL if not set.
1047  **/
1048 const gchar *
1049 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
1050 {
1051     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1052     return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
1053 }
1054
1055 /**
1056  * lightdm_greeter_get_default_session_hint:
1057  * @greeter: A #LightDMGreeter
1058  *
1059  * Get the default session to use.
1060  *
1061  * Return value: The session name
1062  **/
1063 const gchar *
1064 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
1065 {
1066     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1067     return lightdm_greeter_get_hint (greeter, "default-session");
1068 }
1069
1070 /**
1071  * lightdm_greeter_get_hide_users_hint:
1072  * @greeter: A #LightDMGreeter
1073  *
1074  * Check if user accounts should be shown.  If this is TRUE then the list of
1075  * accounts should be taken from #LightDMUserList and displayed in the greeter
1076  * for the user to choose from.  Note that this list can be empty and it is
1077  * recommended you show a method for the user to enter a username manually.
1078  *
1079  * If this option is shown the greeter should only allow these users to be
1080  * chosen for login unless the manual login hint is set.
1081  *
1082  * Return value: #TRUE if the available users should not be shown.
1083  */
1084 gboolean
1085 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
1086 {
1087     const gchar *value;
1088
1089     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1090     value = lightdm_greeter_get_hint (greeter, "hide-users");
1091
1092     return g_strcmp0 (value, "true") == 0;
1093 }
1094
1095 /**
1096  * lightdm_greeter_get_show_manual_login_hint:
1097  * @greeter: A #LightDMGreeter
1098  *
1099  * Check if a manual login option should be shown.  If set the GUI
1100  * should provide a way for a username to be entered manually.
1101  * Without this hint a greeter which is showing a user list can
1102  * limit logins to only those users.
1103  *
1104  * Return value: #TRUE if a manual login option should be shown.
1105  */
1106 gboolean
1107 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
1108 {
1109     const gchar *value;
1110
1111     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1112     value = lightdm_greeter_get_hint (greeter, "show-manual-login");
1113
1114     return g_strcmp0 (value, "true") == 0;
1115 }
1116
1117 /**
1118  * lightdm_greeter_get_show_remote_login_hint:
1119  * @greeter: A #LightDMGreeter
1120  *
1121  * Check if a remote login option should be shown.  If set the GUI
1122  * should provide a way for a user to log into a remote desktop server.
1123  *
1124  * Return value: #TRUE if a remote login option should be shown.
1125  */
1126 gboolean
1127 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
1128 {
1129     const gchar *value;
1130
1131     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1132     value = lightdm_greeter_get_hint (greeter, "show-remote-login");
1133
1134     return g_strcmp0 (value, "true") == 0;
1135 }
1136
1137 /**
1138  * lightdm_greeter_get_lock_hint:
1139  * @greeter: A #LightDMGreeter
1140  *
1141  * Check if the greeter is acting as a lock screen.
1142  *
1143  * Return value: #TRUE if the greeter was triggered by locking the seat.
1144  */
1145 gboolean
1146 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
1147 {
1148     const gchar *value;
1149
1150     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1151     value = lightdm_greeter_get_hint (greeter, "lock-screen");
1152
1153     return g_strcmp0 (value, "true") == 0;
1154 }
1155
1156 /**
1157  * lightdm_greeter_get_has_guest_account_hint:
1158  * @greeter: A #LightDMGreeter
1159  *
1160  * Check if guest sessions are supported.
1161  *
1162  * Return value: #TRUE if guest sessions are supported.
1163  */
1164 gboolean
1165 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
1166 {
1167     const gchar *value;
1168
1169     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1170     value = lightdm_greeter_get_hint (greeter, "has-guest-account");
1171
1172     return g_strcmp0 (value, "true") == 0;
1173 }
1174
1175 /**
1176  * lightdm_greeter_get_select_user_hint:
1177  * @greeter: A #LightDMGreeter
1178  *
1179  * Get the user to select by default.
1180  *
1181  * Return value: (nullable): A username or %NULL if no particular user should be selected.
1182  */
1183 const gchar *
1184 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
1185 {
1186     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1187     return lightdm_greeter_get_hint (greeter, "select-user");
1188 }
1189
1190 /**
1191  * lightdm_greeter_get_select_guest_hint:
1192  * @greeter: A #LightDMGreeter
1193  *
1194  * Check if the guest account should be selected by default.
1195  *
1196  * Return value: #TRUE if the guest account should be selected by default.
1197  */
1198 gboolean
1199 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1200 {
1201     const gchar *value;
1202
1203     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1204     value = lightdm_greeter_get_hint (greeter, "select-guest");
1205
1206     return g_strcmp0 (value, "true") == 0;
1207 }
1208
1209 /**
1210  * lightdm_greeter_get_autologin_user_hint:
1211  * @greeter: A #LightDMGreeter
1212  *
1213  * Get the user account to automatically log into when the timer expires.
1214  *
1215  * Return value: (nullable): The user account to automatically log into or %NULL if none configured.
1216  */
1217 const gchar *
1218 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1219 {
1220     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1221     return lightdm_greeter_get_hint (greeter, "autologin-user");
1222 }
1223
1224 /**
1225  * lightdm_greeter_get_autologin_guest_hint:
1226  * @greeter: A #LightDMGreeter
1227  *
1228  * Check if the guest account should be automatically logged into when the timer expires.
1229  *
1230  * Return value: #TRUE if the guest account should be automatically logged into.
1231  */
1232 gboolean
1233 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1234 {
1235     const gchar *value;
1236
1237     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1238     value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1239
1240     return g_strcmp0 (value, "true") == 0;
1241 }
1242
1243 /**
1244  * lightdm_greeter_get_autologin_timeout_hint:
1245  * @greeter: A #LightDMGreeter
1246  *
1247  * Get the number of seconds to wait before automaitcally logging in.
1248  *
1249  * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1250  */
1251 gint
1252 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1253 {
1254     const gchar *value;
1255     gint timeout = 0;
1256
1257     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1258     value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1259     if (value)
1260         timeout = atoi (value);
1261     if (timeout < 0)
1262         timeout = 0;
1263
1264     return timeout;
1265 }
1266
1267 /**
1268  * lightdm_greeter_cancel_autologin:
1269  * @greeter: A #LightDMGreeter
1270  *
1271  * Cancel the automatic login.
1272  */
1273 void
1274 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1275 {
1276     LightDMGreeterPrivate *priv;
1277
1278     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1279
1280     priv = GET_PRIVATE (greeter);
1281
1282     if (priv->autologin_timeout)
1283        g_source_remove (priv->autologin_timeout);
1284     priv->autologin_timeout = 0;
1285 }
1286
1287 /**
1288  * lightdm_greeter_authenticate:
1289  * @greeter: A #LightDMGreeter
1290  * @username: (allow-none): A username or #NULL to prompt for a username.
1291  * @error: return location for a #GError, or %NULL
1292  *
1293  * Starts the authentication procedure for a user.
1294  *
1295  * Return value: #TRUE if authentication request sent.
1296  **/
1297 gboolean
1298 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username, GError **error)
1299 {
1300     LightDMGreeterPrivate *priv;
1301     guint8 message[MAX_MESSAGE_LENGTH];
1302     gsize offset = 0;
1303
1304     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1305
1306     priv = GET_PRIVATE (greeter);
1307
1308     g_return_val_if_fail (priv->connected, FALSE);
1309
1310     priv->cancelling_authentication = FALSE;
1311     priv->authenticate_sequence_number++;
1312     priv->in_authentication = TRUE;
1313     priv->is_authenticated = FALSE;
1314     if (username != priv->authentication_user)
1315     {
1316         g_free (priv->authentication_user);
1317         priv->authentication_user = g_strdup (username);
1318     }
1319
1320     g_debug ("Starting authentication for user %s...", username);
1321     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset, error) &&
1322            write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1323            write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1324            send_message (greeter, message, offset, error);
1325 }
1326
1327 /**
1328  * lightdm_greeter_authenticate_as_guest:
1329  * @greeter: A #LightDMGreeter
1330  * @error: return location for a #GError, or %NULL
1331  *
1332  * Starts the authentication procedure for the guest user.
1333  *
1334  * Return value: #TRUE if authentication request sent.
1335  **/
1336 gboolean
1337 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter, GError **error)
1338 {
1339     LightDMGreeterPrivate *priv;
1340     guint8 message[MAX_MESSAGE_LENGTH];
1341     gsize offset = 0;
1342
1343     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1344
1345     priv = GET_PRIVATE (greeter);
1346
1347     g_return_val_if_fail (priv->connected, FALSE);
1348
1349     priv->cancelling_authentication = FALSE;
1350     priv->authenticate_sequence_number++;
1351     priv->in_authentication = TRUE;
1352     priv->is_authenticated = FALSE;
1353     g_free (priv->authentication_user);
1354     priv->authentication_user = NULL;
1355
1356     g_debug ("Starting authentication for guest account...");
1357     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset, error) &&
1358            write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1359            send_message (greeter, message, offset, error);
1360 }
1361
1362 /**
1363  * lightdm_greeter_authenticate_autologin:
1364  * @greeter: A #LightDMGreeter
1365  * @error: return location for a #GError, or %NULL
1366  *
1367  * Starts the authentication procedure for the automatic login user.
1368  *
1369  * Return value: #TRUE if authentication request sent.
1370  **/
1371 gboolean
1372 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter, GError **error)
1373 {
1374     const gchar *user;
1375
1376     user = lightdm_greeter_get_autologin_user_hint (greeter);
1377     if (lightdm_greeter_get_autologin_guest_hint (greeter))
1378         return lightdm_greeter_authenticate_as_guest (greeter, error);
1379     else if (user)
1380         return lightdm_greeter_authenticate (greeter, user, error);
1381     else
1382     {
1383         g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_NO_AUTOLOGIN,
1384                              "Can't authenticate autologin; autologin not configured");
1385         return FALSE;
1386     }
1387 }
1388
1389 /**
1390  * lightdm_greeter_authenticate_remote:
1391  * @greeter: A #LightDMGreeter
1392  * @session: The name of a remote session
1393  * @username: (allow-none): A username of #NULL to prompt for a username.
1394  * @error: return location for a #GError, or %NULL
1395  *
1396  * Start authentication for a remote session type.
1397  *
1398  * Return value: #TRUE if authentication request sent.
1399  **/
1400 gboolean
1401 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username, GError **error)
1402 {
1403     LightDMGreeterPrivate *priv;
1404     guint8 message[MAX_MESSAGE_LENGTH];
1405     gsize offset = 0;
1406
1407     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1408
1409     priv = GET_PRIVATE (greeter);
1410
1411     g_return_val_if_fail (priv->connected, FALSE);
1412
1413     priv->cancelling_authentication = FALSE;
1414     priv->authenticate_sequence_number++;
1415     priv->in_authentication = TRUE;
1416     priv->is_authenticated = FALSE;
1417     g_free (priv->authentication_user);
1418     priv->authentication_user = NULL;
1419
1420     if (username)
1421         g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1422     else
1423         g_debug ("Starting authentication for remote session %s...", session);
1424
1425     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset, error) &&
1426            write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset, error) &&
1427            write_string (message, MAX_MESSAGE_LENGTH, session, &offset, error) &&
1428            write_string (message, MAX_MESSAGE_LENGTH, username, &offset, error) &&
1429            send_message (greeter, message, offset, error);
1430 }
1431
1432 /**
1433  * lightdm_greeter_respond:
1434  * @greeter: A #LightDMGreeter
1435  * @response: Response to a prompt
1436  * @error: return location for a #GError, or %NULL
1437  *
1438  * Provide response to a prompt.  May be one in a series.
1439  *
1440  * Return value: #TRUE if response sent.
1441  **/
1442 gboolean
1443 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response, GError **error)
1444 {
1445     LightDMGreeterPrivate *priv;
1446     guint8 message[MAX_MESSAGE_LENGTH];
1447     gsize offset = 0;
1448
1449     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1450     g_return_val_if_fail (response != NULL, FALSE);
1451
1452     priv = GET_PRIVATE (greeter);
1453
1454     g_return_val_if_fail (priv->connected, FALSE);
1455     g_return_val_if_fail (priv->n_responses_waiting > 0, FALSE);
1456
1457     priv->n_responses_waiting--;
1458     priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1459
1460     if (priv->n_responses_waiting == 0)
1461     {
1462         guint32 msg_length;
1463         GList *iter;
1464
1465         g_debug ("Providing response to display manager");
1466
1467         msg_length = int_length ();
1468         for (iter = priv->responses_received; iter; iter = iter->next)
1469             msg_length += string_length ((gchar *)iter->data);
1470
1471         if (!write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset, error) ||
1472             !write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset, error))
1473             return FALSE;
1474         for (iter = priv->responses_received; iter; iter = iter->next)
1475         {
1476             if (!write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset, error))
1477                 return FALSE;
1478         }
1479         if (!send_message (greeter, message, offset, error))
1480             return FALSE;
1481
1482         g_list_free_full (priv->responses_received, g_free);
1483         priv->responses_received = NULL;
1484     }
1485
1486     return TRUE;
1487 }
1488
1489 /**
1490  * lightdm_greeter_cancel_authentication:
1491  * @greeter: A #LightDMGreeter
1492  * @error: return location for a #GError, or %NULL
1493  *
1494  * Cancel the current user authentication.
1495  *
1496  * Return value: #TRUE if cancel request sent.
1497  **/
1498 gboolean
1499 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter, GError **error)
1500 {
1501     LightDMGreeterPrivate *priv;
1502     guint8 message[MAX_MESSAGE_LENGTH];
1503     gsize offset = 0;
1504
1505     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1506
1507     priv = GET_PRIVATE (greeter);
1508
1509     g_return_val_if_fail (priv->connected, FALSE);
1510
1511     priv->cancelling_authentication = TRUE;
1512     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset, error) &&
1513            send_message (greeter, message, offset, error);
1514 }
1515
1516 /**
1517  * lightdm_greeter_get_in_authentication:
1518  * @greeter: A #LightDMGreeter
1519  *
1520  * Checks if the greeter is in the process of authenticating.
1521  *
1522  * Return value: #TRUE if the greeter is authenticating a user.
1523  **/
1524 gboolean
1525 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1526 {
1527     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1528     return GET_PRIVATE (greeter)->in_authentication;
1529 }
1530
1531 /**
1532  * lightdm_greeter_get_is_authenticated:
1533  * @greeter: A #LightDMGreeter
1534  *
1535  * Checks if the greeter has successfully authenticated.
1536  *
1537  * Return value: #TRUE if the greeter is authenticated for login.
1538  **/
1539 gboolean
1540 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1541 {
1542     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1543     return GET_PRIVATE (greeter)->is_authenticated;
1544 }
1545
1546 /**
1547  * lightdm_greeter_get_authentication_user:
1548  * @greeter: A #LightDMGreeter
1549  *
1550  * Get the user that is being authenticated.
1551  *
1552  * Return value: (nullable): The username of the authentication user being authenticated or #NULL if no authentication in progress.
1553  */
1554 const gchar *
1555 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1556 {
1557     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1558     return GET_PRIVATE (greeter)->authentication_user;
1559 }
1560
1561 /**
1562  * lightdm_greeter_set_language:
1563  * @greeter: A #LightDMGreeter
1564  * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1565  * @error: return location for a #GError, or %NULL
1566  *
1567  * Set the language for the currently authenticated user.
1568  *
1569  * Return value: #TRUE if set language request sent.
1570  **/
1571 gboolean
1572 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language, GError **error)
1573 {
1574     LightDMGreeterPrivate *priv;
1575     guint8 message[MAX_MESSAGE_LENGTH];
1576     gsize offset = 0;
1577
1578     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1579
1580     priv = GET_PRIVATE (greeter);
1581
1582     g_return_val_if_fail (priv->connected, FALSE);
1583
1584     return write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset, error) &&
1585            write_string (message, MAX_MESSAGE_LENGTH, language, &offset, error) &&
1586            send_message (greeter, message, offset, error);
1587 }
1588
1589 /**
1590  * lightdm_greeter_start_session:
1591  * @greeter: A #LightDMGreeter
1592  * @session: (allow-none): The session to log into or #NULL to use the default.
1593  * @cancellable: (allow-none): A #GCancellable or %NULL.
1594  * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1595  * @user_data: (allow-none): data to pass to the @callback or %NULL.
1596  *
1597  * Asynchronously start a session for the authenticated user.
1598  *
1599  * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_start_session_finish() to get the result of the operation.
1600  *
1601  * See lightdm_greeter_start_session_sync() for the synchronous version.
1602  **/
1603 void
1604 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1605 {
1606     LightDMGreeterPrivate *priv;
1607     Request *request;
1608     GError *error = NULL;
1609
1610     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1611
1612     priv = GET_PRIVATE (greeter);
1613
1614     request = request_new (greeter, cancellable, callback, user_data);
1615     priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1616     if (!send_start_session (greeter, session, &error))
1617     {
1618         request->error = error;
1619         request_complete (request);
1620     }
1621 }
1622
1623 /**
1624  * lightdm_greeter_start_session_finish:
1625  * @greeter: A #LightDMGreeter
1626  * @result: A #GAsyncResult.
1627  * @error: return location for a #GError, or %NULL
1628  *
1629  * Start a session for the authenticated user.
1630  *
1631  * Return value: TRUE if the session was started.
1632  **/
1633 gboolean
1634 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1635 {
1636     Request *request = REQUEST (result);
1637
1638     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1639
1640     g_propagate_error (error, request->error);
1641     return request->result;
1642 }
1643
1644 /**
1645  * lightdm_greeter_start_session_sync:
1646  * @greeter: A #LightDMGreeter
1647  * @session: (allow-none): The session to log into or #NULL to use the default.
1648  * @error: return location for a #GError, or %NULL
1649  *
1650  * Start a session for the authenticated user.
1651  *
1652  * Return value: TRUE if the session was started.
1653  **/
1654 gboolean
1655 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1656 {
1657     LightDMGreeterPrivate *priv;
1658     Request *request;
1659
1660     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1661
1662     priv = GET_PRIVATE (greeter);
1663
1664     g_return_val_if_fail (priv->connected, FALSE);
1665     g_return_val_if_fail (priv->is_authenticated, FALSE);
1666
1667     /* Read until the session is started */
1668     if (!send_start_session (greeter, session, error))
1669         return FALSE;
1670     request = request_new (greeter, NULL, NULL, NULL);
1671     priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1672     do
1673     {
1674         guint8 *message;
1675         gsize message_length;
1676
1677         if (!recv_message (greeter, TRUE, &message, &message_length, error))
1678             return FALSE;
1679         handle_message (greeter, message, message_length);
1680         g_free (message);
1681     } while (!request->complete);
1682
1683     return lightdm_greeter_start_session_finish (greeter, G_ASYNC_RESULT (request), error);
1684 }
1685
1686 /**
1687  * lightdm_greeter_ensure_shared_data_dir:
1688  * @greeter: A #LightDMGreeter
1689  * @username: A username
1690  * @cancellable: (allow-none): A #GCancellable or %NULL.
1691  * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1692  * @user_data: (allow-none): data to pass to the @callback or %NULL.
1693  *
1694  * Ensure that a shared data dir for the given user is available.  Both the
1695  * greeter user and @username will have write access to that folder.  The
1696  * intention is that larger pieces of shared data would be stored there (files
1697  * that the greeter creates but wants to give to a user -- like camera
1698  * photos -- or files that the user creates but wants the greeter to
1699  * see -- like contact avatars).
1700  *
1701  * LightDM will automatically create these if the user actually logs in, so
1702  * greeters only need to call this method if they want to store something in
1703  * the directory themselves.
1704  **/
1705 void
1706 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1707 {
1708     LightDMGreeterPrivate *priv;
1709     Request *request;
1710     GError *error = NULL;
1711
1712     g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1713
1714     priv = GET_PRIVATE (greeter);
1715
1716     request = request_new (greeter, cancellable, callback, user_data);
1717     priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1718     if (!send_ensure_shared_data_dir (greeter, username, &error))
1719     {
1720         request->error = error;
1721         request_complete (request);
1722     }
1723 }
1724
1725 /**
1726  * lightdm_greeter_ensure_shared_data_dir_finish:
1727  * @result: A #GAsyncResult.
1728  * @greeter: A #LightDMGreeter
1729  * @error: return location for a #GError, or %NULL
1730  *
1731  * Function to call from lightdm_greeter_ensure_shared_data_dir callback.
1732  *
1733  * Return value: The path to the shared directory, free with g_free.
1734  **/
1735 gchar *
1736 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1737 {
1738     Request *request = REQUEST (result);
1739
1740     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1741
1742     g_propagate_error (error, request->error);
1743     return g_strdup (request->dir);
1744 }
1745
1746 /**
1747  * lightdm_greeter_ensure_shared_data_dir_sync:
1748  * @greeter: A #LightDMGreeter
1749  * @username: A username
1750  * @error: return location for a #GError, or %NULL
1751  *
1752  * Ensure that a shared data dir for the given user is available.  Both the
1753  * greeter user and @username will have write access to that folder.  The
1754  * intention is that larger pieces of shared data would be stored there (files
1755  * that the greeter creates but wants to give to a user -- like camera
1756  * photos -- or files that the user creates but wants the greeter to
1757  * see -- like contact avatars).
1758  *
1759  * LightDM will automatically create these if the user actually logs in, so
1760  * greeters only need to call this method if they want to store something in
1761  * the directory themselves.
1762  *
1763  * Return value: The path to the shared directory, free with g_free.
1764  **/
1765 gchar *
1766 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username, GError **error)
1767 {
1768     LightDMGreeterPrivate *priv;
1769     Request *request;
1770
1771     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1772
1773     priv = GET_PRIVATE (greeter);
1774
1775     g_return_val_if_fail (priv->connected, NULL);
1776
1777     /* Read until a response */
1778     if (!send_ensure_shared_data_dir (greeter, username, error))
1779         return NULL;
1780     request = request_new (greeter, NULL, NULL, NULL);
1781     priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1782     do
1783     {
1784         guint8 *message;
1785         gsize message_length;
1786
1787         if (!recv_message (greeter, TRUE, &message, &message_length, error))
1788             return FALSE;
1789         handle_message (greeter, message, message_length);
1790         g_free (message);
1791     } while (!request->complete);
1792
1793     return lightdm_greeter_ensure_shared_data_dir_finish (greeter, G_ASYNC_RESULT (request), error);
1794 }
1795
1796 static void
1797 lightdm_greeter_init (LightDMGreeter *greeter)
1798 {
1799     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1800
1801     priv->read_buffer = g_malloc (HEADER_SIZE);
1802     priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1803 }
1804
1805 static void
1806 lightdm_greeter_set_property (GObject      *object,
1807                               guint         prop_id,
1808                               const GValue *value,
1809                               GParamSpec   *pspec)
1810 {
1811     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1812 }
1813
1814 static void
1815 lightdm_greeter_get_property (GObject    *object,
1816                               guint       prop_id,
1817                               GValue     *value,
1818                               GParamSpec *pspec)
1819 {
1820     LightDMGreeter *self;
1821
1822     self = LIGHTDM_GREETER (object);
1823
1824     switch (prop_id) {
1825     case PROP_DEFAULT_SESSION_HINT:
1826         g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1827         break;
1828     case PROP_HIDE_USERS_HINT:
1829         g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1830         break;
1831     case PROP_SHOW_MANUAL_LOGIN_HINT:
1832         g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1833         break;
1834     case PROP_SHOW_REMOTE_LOGIN_HINT:
1835         g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1836         break;
1837     case PROP_LOCK_HINT:
1838         g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1839         break;
1840     case PROP_HAS_GUEST_ACCOUNT_HINT:
1841         g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1842         break;
1843     case PROP_SELECT_USER_HINT:
1844         g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1845         break;
1846     case PROP_SELECT_GUEST_HINT:
1847         g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1848         break;
1849     case PROP_AUTOLOGIN_USER_HINT:
1850         g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1851         break;
1852     case PROP_AUTOLOGIN_GUEST_HINT:
1853         g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1854         break;
1855     case PROP_AUTOLOGIN_TIMEOUT_HINT:
1856         g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1857         break;
1858     case PROP_AUTHENTICATION_USER:
1859         g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1860         break;
1861     case PROP_IN_AUTHENTICATION:
1862         g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1863         break;
1864     case PROP_IS_AUTHENTICATED:
1865         g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1866         break;
1867     default:
1868         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1869         break;
1870     }
1871 }
1872
1873 static void
1874 lightdm_greeter_finalize (GObject *object)
1875 {
1876     LightDMGreeter *self = LIGHTDM_GREETER (object);
1877     LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1878
1879     g_clear_object (&priv->socket);
1880     if (priv->to_server_channel)
1881         g_io_channel_unref (priv->to_server_channel);
1882     if (priv->from_server_channel)
1883         g_io_channel_unref (priv->from_server_channel);
1884     g_free (priv->authentication_user);
1885     g_hash_table_unref (priv->hints);
1886
1887     G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1888 }
1889
1890 static void
1891 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1892 {
1893     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1894
1895     g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1896
1897     object_class->set_property = lightdm_greeter_set_property;
1898     object_class->get_property = lightdm_greeter_get_property;
1899     object_class->finalize = lightdm_greeter_finalize;
1900
1901     g_object_class_install_property (object_class,
1902                                      PROP_DEFAULT_SESSION_HINT,
1903                                      g_param_spec_string ("default-session-hint",
1904                                                           "default-session-hint",
1905                                                           "Default session hint",
1906                                                           NULL,
1907                                                           G_PARAM_READABLE));
1908
1909     g_object_class_install_property (object_class,
1910                                      PROP_HIDE_USERS_HINT,
1911                                      g_param_spec_boolean ("hide-users-hint",
1912                                                            "hide-users-hint",
1913                                                            "Hide users hint",
1914                                                            FALSE,
1915                                                            G_PARAM_READABLE));
1916
1917     g_object_class_install_property (object_class,
1918                                      PROP_SHOW_MANUAL_LOGIN_HINT,
1919                                      g_param_spec_boolean ("show-manual-login-hint",
1920                                                            "show-manual-login-hint",
1921                                                            "Show manual login hint",
1922                                                            FALSE,
1923                                                            G_PARAM_READABLE));
1924
1925     g_object_class_install_property (object_class,
1926                                      PROP_SHOW_REMOTE_LOGIN_HINT,
1927                                      g_param_spec_boolean ("show-remote-login-hint",
1928                                                            "show-remote-login-hint",
1929                                                            "Show remote login hint",
1930                                                            FALSE,
1931                                                            G_PARAM_READABLE));
1932
1933     g_object_class_install_property (object_class,
1934                                      PROP_LOCK_HINT,
1935                                      g_param_spec_boolean ("lock-hint",
1936                                                            "lock-hint",
1937                                                            "Lock hint",
1938                                                            FALSE,
1939                                                            G_PARAM_READABLE));
1940
1941     g_object_class_install_property (object_class,
1942                                      PROP_HAS_GUEST_ACCOUNT_HINT,
1943                                      g_param_spec_boolean ("has-guest-account-hint",
1944                                                            "has-guest-account-hint",
1945                                                            "Has guest account hint",
1946                                                            FALSE,
1947                                                            G_PARAM_READABLE));
1948
1949     g_object_class_install_property (object_class,
1950                                      PROP_SELECT_USER_HINT,
1951                                      g_param_spec_string ("select-user-hint",
1952                                                           "select-user-hint",
1953                                                           "Select user hint",
1954                                                           NULL,
1955                                                           G_PARAM_READABLE));
1956
1957     g_object_class_install_property (object_class,
1958                                      PROP_SELECT_GUEST_HINT,
1959                                      g_param_spec_boolean ("select-guest-hint",
1960                                                            "select-guest-hint",
1961                                                            "Select guest account hint",
1962                                                            FALSE,
1963                                                            G_PARAM_READABLE));
1964
1965     g_object_class_install_property (object_class,
1966                                      PROP_AUTOLOGIN_USER_HINT,
1967                                      g_param_spec_string ("autologin-user-hint",
1968                                                           "autologin-user-hint",
1969                                                           "Autologin user hint",
1970                                                           NULL,
1971                                                           G_PARAM_READABLE));
1972
1973     g_object_class_install_property (object_class,
1974                                      PROP_AUTOLOGIN_GUEST_HINT,
1975                                      g_param_spec_boolean ("autologin-guest-hint",
1976                                                            "autologin-guest-hint",
1977                                                            "Autologin guest account hint",
1978                                                            FALSE,
1979                                                            G_PARAM_READABLE));
1980
1981     g_object_class_install_property (object_class,
1982                                      PROP_AUTOLOGIN_TIMEOUT_HINT,
1983                                      g_param_spec_int ("autologin-timeout-hint",
1984                                                        "autologin-timeout-hint",
1985                                                        "Autologin timeout hint",
1986                                                        0, G_MAXINT, 0,
1987                                                        G_PARAM_READABLE));
1988
1989     g_object_class_install_property (object_class,
1990                                      PROP_AUTHENTICATION_USER,
1991                                      g_param_spec_string ("authentication-user",
1992                                                           "authentication-user",
1993                                                           "The user being authenticated",
1994                                                           NULL,
1995                                                           G_PARAM_READABLE));
1996     g_object_class_install_property (object_class,
1997                                      PROP_IN_AUTHENTICATION,
1998                                      g_param_spec_boolean ("in-authentication",
1999                                                            "in-authentication",
2000                                                            "TRUE if a user is being authenticated",
2001                                                            FALSE,
2002                                                            G_PARAM_READABLE));
2003     g_object_class_install_property (object_class,
2004                                      PROP_IS_AUTHENTICATED,
2005                                      g_param_spec_boolean ("is-authenticated",
2006                                                            "is-authenticated",
2007                                                            "TRUE if the selected user is authenticated",
2008                                                            FALSE,
2009                                                            G_PARAM_READABLE));
2010
2011     /**
2012      * LightDMGreeter::show-prompt:
2013      * @greeter: A #LightDMGreeter
2014      * @text: Prompt text
2015      * @type: Prompt type
2016      *
2017      * The ::show-prompt signal gets emitted when the greeter should show a
2018      * prompt to the user.  The given text should be displayed and an input
2019      * field for the user to provide a response.
2020      *
2021      * Call lightdm_greeter_respond() with the resultant input or
2022      * lightdm_greeter_cancel_authentication() to abort the authentication.
2023      **/
2024     signals[SHOW_PROMPT] =
2025         g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
2026                       G_TYPE_FROM_CLASS (klass),
2027                       G_SIGNAL_RUN_LAST,
2028                       G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
2029                       NULL, NULL,
2030                       NULL,
2031                       G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_prompt_type_get_type ());
2032
2033     /**
2034      * LightDMGreeter::show-message:
2035      * @greeter: A #LightDMGreeter
2036      * @text: Message text
2037      * @type: Message type
2038      *
2039      * The ::show-message signal gets emitted when the greeter
2040      * should show a message to the user.
2041      **/
2042     signals[SHOW_MESSAGE] =
2043         g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
2044                       G_TYPE_FROM_CLASS (klass),
2045                       G_SIGNAL_RUN_LAST,
2046                       G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
2047                       NULL, NULL,
2048                       NULL,
2049                       G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_message_type_get_type ());
2050
2051     /**
2052      * LightDMGreeter::authentication-complete:
2053      * @greeter: A #LightDMGreeter
2054      *
2055      * The ::authentication-complete signal gets emitted when the greeter
2056      * has completed authentication.
2057      *
2058      * Call lightdm_greeter_get_is_authenticated() to check if the authentication
2059      * was successful.
2060      **/
2061     signals[AUTHENTICATION_COMPLETE] =
2062         g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
2063                       G_TYPE_FROM_CLASS (klass),
2064                       G_SIGNAL_RUN_LAST,
2065                       G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
2066                       NULL, NULL,
2067                       NULL,
2068                       G_TYPE_NONE, 0);
2069
2070     /**
2071      * LightDMGreeter::autologin-timer-expired:
2072      * @greeter: A #LightDMGreeter
2073      *
2074      * The ::timed-login signal gets emitted when the automatic login timer has expired.
2075      * The application should then call lightdm_greeter_login().
2076      **/
2077     signals[AUTOLOGIN_TIMER_EXPIRED] =
2078         g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
2079                       G_TYPE_FROM_CLASS (klass),
2080                       G_SIGNAL_RUN_LAST,
2081                       G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
2082                       NULL, NULL,
2083                       NULL,
2084                       G_TYPE_NONE, 0);
2085
2086     /**
2087      * LightDMGreeter::idle:
2088      * @greeter: A #LightDMGreeter
2089      *
2090      * The ::idle signal gets emitted when the user has logged in and the
2091      * greeter is no longer needed.
2092      *
2093      * This signal only matters if the greeter has marked itself as
2094      * resettable using lightdm_greeter_set_resettable().
2095      **/
2096     signals[IDLE] =
2097         g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
2098                       G_TYPE_FROM_CLASS (klass),
2099                       G_SIGNAL_RUN_LAST,
2100                       G_STRUCT_OFFSET (LightDMGreeterClass, idle),
2101                       NULL, NULL,
2102                       NULL,
2103                       G_TYPE_NONE, 0);
2104
2105     /**
2106      * LightDMGreeter::reset:
2107      * @greeter: A #LightDMGreeter
2108      *
2109      * The ::reset signal gets emitted when the user is returning to a greeter
2110      * that was previously marked idle.
2111      *
2112      * This signal only matters if the greeter has marked itself as
2113      * resettable using lightdm_greeter_set_resettable().
2114      **/
2115     signals[RESET] =
2116         g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
2117                       G_TYPE_FROM_CLASS (klass),
2118                       G_SIGNAL_RUN_LAST,
2119                       G_STRUCT_OFFSET (LightDMGreeterClass, reset),
2120                       NULL, NULL,
2121                       NULL,
2122                       G_TYPE_NONE, 0);
2123 }
2124
2125 static void
2126 request_init (Request *request)
2127 {
2128 }
2129
2130 static void
2131 request_finalize (GObject *object)
2132 {
2133     Request *request = REQUEST (object);
2134
2135     g_clear_object (&request->greeter);
2136     g_clear_object (&request->cancellable);
2137     g_free (request->dir);
2138
2139     G_OBJECT_CLASS (request_parent_class)->finalize (object);
2140 }
2141
2142 static void
2143 request_class_init (RequestClass *klass)
2144 {
2145     GObjectClass *object_class = G_OBJECT_CLASS (klass);
2146     object_class->finalize = request_finalize;
2147 }
2148
2149 static gpointer
2150 request_get_user_data (GAsyncResult *result)
2151 {
2152     return REQUEST (result)->user_data;
2153 }
2154
2155 static GObject *
2156 request_get_source_object (GAsyncResult *result)
2157 {
2158     return g_object_ref (REQUEST (result)->greeter);
2159 }
2160
2161 static void
2162 request_iface_init (GAsyncResultIface *iface)
2163 {
2164     iface->get_user_data = request_get_user_data;
2165     iface->get_source_object = request_get_source_object;
2166 }