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