]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/greeter.c
4534ee2fc0f175e7293936573361d29da0febc52
[sojka/lightdm.git] / src / greeter.c
1 /*
2  * Copyright (C) 2010-2016 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free Software
6  * Foundation, either version 3 of the License, or (at your option) any later
7  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
8  * license.
9  */
10
11 #include <config.h>
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <gcrypt.h>
16
17 #include "greeter.h"
18 #include "configuration.h"
19 #include "shared-data-manager.h"
20
21 enum {
22     PROP_0,
23     PROP_ACTIVE_USERNAME,
24 };
25
26 enum {
27     CONNECTED,
28     CREATE_SESSION,
29     START_SESSION,
30     LAST_SIGNAL
31 };
32 static guint signals[LAST_SIGNAL] = { 0 };
33
34 struct GreeterPrivate
35 {
36     /* PAM service to authenticate with */
37     gchar *pam_service;
38     gchar *autologin_pam_service;
39
40     /* Buffer for data read from greeter */
41     guint8 *read_buffer;
42     gsize n_read;
43     gboolean use_secure_memory;
44
45     /* Hints for the greeter */
46     GHashTable *hints;
47
48     /* Default session to use */
49     gchar *default_session;
50
51     /* Sequence number of current PAM session */
52     guint32 authentication_sequence_number;
53
54     /* Remote session name */
55     gchar *remote_session;
56
57     /* Currently selected user */
58     gchar *active_username;
59
60     /* PAM session being constructed by the greeter */
61     Session *authentication_session;
62
63     /* TRUE if a the greeter can handle a reset; else we will just kill it instead */
64     gboolean resettable;
65
66     /* TRUE if a user has been authenticated and the session requested to start */
67     gboolean start_session;
68
69     /* TRUE if can log into guest accounts */
70     gboolean allow_guest;
71
72     /* TRUE if logging into guest session */
73     gboolean guest_account_authenticated;
74
75     /* Communication channels to communicate with */
76     int to_greeter_input;
77     int from_greeter_output;
78     GIOChannel *to_greeter_channel;
79     GIOChannel *from_greeter_channel;
80     guint from_greeter_watch;
81 };
82
83 G_DEFINE_TYPE (Greeter, greeter, G_TYPE_OBJECT);
84
85 /* Messages from the greeter to the server */
86 typedef enum
87 {
88     GREETER_MESSAGE_CONNECT = 0,
89     GREETER_MESSAGE_AUTHENTICATE,
90     GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
91     GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
92     GREETER_MESSAGE_START_SESSION,
93     GREETER_MESSAGE_CANCEL_AUTHENTICATION,
94     GREETER_MESSAGE_SET_LANGUAGE,
95     GREETER_MESSAGE_AUTHENTICATE_REMOTE,
96     GREETER_MESSAGE_ENSURE_SHARED_DIR,
97 } GreeterMessage;
98
99 /* Messages from the server to the greeter */
100 typedef enum
101 {
102     SERVER_MESSAGE_CONNECTED = 0,
103     SERVER_MESSAGE_PROMPT_AUTHENTICATION,
104     SERVER_MESSAGE_END_AUTHENTICATION,
105     SERVER_MESSAGE_SESSION_RESULT,
106     SERVER_MESSAGE_SHARED_DIR_RESULT,
107     SERVER_MESSAGE_IDLE,
108     SERVER_MESSAGE_RESET,
109 } ServerMessage;
110
111 static gboolean read_cb (GIOChannel *source, GIOCondition condition, gpointer data);
112
113 Greeter *
114 greeter_new (void)
115 {
116     return g_object_new (GREETER_TYPE, NULL);
117 }
118
119 void
120 greeter_set_file_descriptors (Greeter *greeter, int to_greeter_fd, int from_greeter_fd)
121 {
122     GError *error = NULL;
123
124     g_return_if_fail (greeter != NULL);
125     g_return_if_fail (greeter->priv->to_greeter_input < 0);
126     g_return_if_fail (greeter->priv->from_greeter_output < 0);
127
128     greeter->priv->to_greeter_input = to_greeter_fd;  
129     greeter->priv->to_greeter_channel = g_io_channel_unix_new (greeter->priv->to_greeter_input);
130     g_io_channel_set_encoding (greeter->priv->to_greeter_channel, NULL, &error);
131     if (error)
132         g_warning ("Failed to set encoding on to greeter channel to binary: %s\n", error->message);
133     g_clear_error (&error);
134     greeter->priv->from_greeter_output = from_greeter_fd;
135     greeter->priv->from_greeter_channel = g_io_channel_unix_new (greeter->priv->from_greeter_output);
136     g_io_channel_set_encoding (greeter->priv->from_greeter_channel, NULL, &error);
137     if (error)
138         g_warning ("Failed to set encoding on from greeter channel to binary: %s\n", error->message);
139     g_clear_error (&error);
140     g_io_channel_set_buffered (greeter->priv->from_greeter_channel, FALSE);
141     greeter->priv->from_greeter_watch = g_io_add_watch (greeter->priv->from_greeter_channel, G_IO_IN | G_IO_HUP, read_cb, greeter);
142 }
143
144 void
145 greeter_stop (Greeter *greeter)
146 {
147     /* Stop any events occurring after we've stopped */
148     if (greeter->priv->authentication_session)
149         g_signal_handlers_disconnect_matched (greeter->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, greeter);
150 }
151
152 void
153 greeter_set_pam_services (Greeter *greeter, const gchar *pam_service, const gchar *autologin_pam_service)
154 {
155     g_return_if_fail (greeter != NULL);
156     g_free (greeter->priv->pam_service);
157     greeter->priv->pam_service = g_strdup (pam_service);
158     g_free (greeter->priv->autologin_pam_service);
159     greeter->priv->autologin_pam_service = g_strdup (autologin_pam_service);
160 }
161
162 void
163 greeter_set_allow_guest (Greeter *greeter, gboolean allow_guest)
164 {
165     g_return_if_fail (greeter != NULL);  
166     greeter->priv->allow_guest = allow_guest;
167 }
168
169 void
170 greeter_clear_hints (Greeter *greeter)
171 {
172     g_return_if_fail (greeter != NULL);
173     g_hash_table_remove_all (greeter->priv->hints);
174 }
175
176 void
177 greeter_set_hint (Greeter *greeter, const gchar *name, const gchar *value)
178 {
179     g_return_if_fail (greeter != NULL);
180     g_hash_table_insert (greeter->priv->hints, g_strdup (name), g_strdup (value));
181 }
182
183 static void *
184 secure_malloc (Greeter *greeter, size_t n)
185 {
186     if (greeter->priv->use_secure_memory)
187         return gcry_malloc_secure (n);
188     else
189         return g_malloc (n);
190 }
191
192 static void *
193 secure_realloc (Greeter *greeter, void *ptr, size_t n)
194 {
195     if (greeter->priv->use_secure_memory)
196         return gcry_realloc (ptr, n);
197     else
198         return g_realloc (ptr, n);
199 }
200
201 static void
202 secure_free (Greeter *greeter, void *ptr)
203 {
204     if (greeter->priv->use_secure_memory)
205         return gcry_free (ptr);
206     else
207         return g_free (ptr);
208 }
209
210 static guint32
211 int_length (void)
212 {
213     return 4;
214 }
215
216 #define HEADER_SIZE (sizeof (guint32) * 2)
217 #define MAX_MESSAGE_LENGTH 1024
218
219 static void
220 write_message (Greeter *greeter, guint8 *message, gsize message_length)
221 {
222     gchar *data;
223     gsize data_length;
224     GError *error = NULL;
225
226     data = (gchar *) message;
227     data_length = message_length;
228     while (data_length > 0)
229     {
230         GIOStatus status;
231         gsize n_written;
232
233         status = g_io_channel_write_chars (greeter->priv->to_greeter_channel, data, data_length, &n_written, &error);
234         if (error)
235             g_warning ("Error writing to greeter: %s", error->message);
236         g_clear_error (&error);
237         if (status != G_IO_STATUS_NORMAL)
238             return;
239         data_length -= n_written;
240         data += n_written;
241     }
242
243     g_io_channel_flush (greeter->priv->to_greeter_channel, &error);
244     if (error)
245         g_warning ("Failed to flush data to greeter: %s", error->message);
246     g_clear_error (&error);
247 }
248
249 static void
250 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
251 {
252     if (*offset + 4 >= buffer_length)
253         return;
254     buffer[*offset] = value >> 24;
255     buffer[*offset+1] = (value >> 16) & 0xFF;
256     buffer[*offset+2] = (value >> 8) & 0xFF;
257     buffer[*offset+3] = value & 0xFF;
258     *offset += 4;
259 }
260
261 static void
262 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
263 {
264     gint length;
265
266     if (value)
267         length = strlen (value);
268     else
269         length = 0;
270     write_int (buffer, buffer_length, length, offset);
271     if (*offset + length >= buffer_length)
272         return;
273     if (length > 0)
274     {
275         memcpy (buffer + *offset, value, length);
276         *offset += length;
277     }
278 }
279
280 static void
281 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
282 {
283     write_int (buffer, buffer_length, id, offset);
284     write_int (buffer, buffer_length, length, offset);
285 }
286
287 static guint32
288 string_length (const gchar *value)
289 {
290     if (value == NULL)
291         return int_length ();
292     else
293         return int_length () + strlen (value);
294 }
295
296 static void
297 handle_connect (Greeter *greeter, const gchar *version, gboolean resettable)
298 {
299     guint8 message[MAX_MESSAGE_LENGTH];
300     gsize offset = 0;
301     guint32 length;
302     GHashTableIter iter;
303     gpointer key, value;
304
305     g_debug ("Greeter connected version=%s resettable=%s", version, resettable ? "true" : "false");
306
307     greeter->priv->resettable = resettable;
308
309     length = string_length (VERSION);
310     g_hash_table_iter_init (&iter, greeter->priv->hints);
311     while (g_hash_table_iter_next (&iter, &key, &value))
312         length += string_length (key) + string_length (value);
313
314     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_CONNECTED, length, &offset);
315     write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
316     g_hash_table_iter_init (&iter, greeter->priv->hints);
317     while (g_hash_table_iter_next (&iter, &key, &value))
318     {
319         write_string (message, MAX_MESSAGE_LENGTH, key, &offset);
320         write_string (message, MAX_MESSAGE_LENGTH, value, &offset);
321     }
322     write_message (greeter, message, offset);
323
324     g_signal_emit (greeter, signals[CONNECTED], 0);
325 }
326
327 static void
328 pam_messages_cb (Session *session, Greeter *greeter)
329 {
330     int i;
331     guint32 size;
332     guint8 message[MAX_MESSAGE_LENGTH];
333     const struct pam_message *messages;
334     int messages_length;
335     gsize offset = 0;
336     int n_prompts = 0;
337
338     messages = session_get_messages (session);
339     messages_length = session_get_messages_length (session);
340
341     /* Respond to d-bus query with messages */
342     g_debug ("Prompt greeter with %d message(s)", messages_length);
343     size = int_length () + string_length (session_get_username (session)) + int_length ();
344     for (i = 0; i < messages_length; i++)
345         size += int_length () + string_length (messages[i].msg);
346
347     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_PROMPT_AUTHENTICATION, size, &offset);
348     write_int (message, MAX_MESSAGE_LENGTH, greeter->priv->authentication_sequence_number, &offset);
349     write_string (message, MAX_MESSAGE_LENGTH, session_get_username (session), &offset);
350     write_int (message, MAX_MESSAGE_LENGTH, messages_length, &offset);
351     for (i = 0; i < messages_length; i++)
352     {
353         write_int (message, MAX_MESSAGE_LENGTH, messages[i].msg_style, &offset);
354         write_string (message, MAX_MESSAGE_LENGTH, messages[i].msg, &offset);
355
356         if (messages[i].msg_style == PAM_PROMPT_ECHO_OFF || messages[i].msg_style == PAM_PROMPT_ECHO_ON)
357             n_prompts++;
358     }
359     write_message (greeter, message, offset);
360
361     /* Continue immediately if nothing to respond with */
362     // FIXME: Should probably give the greeter a chance to ack the message
363     if (n_prompts == 0)
364     {
365         struct pam_response *response;
366         response = calloc (messages_length, sizeof (struct pam_response));
367         session_respond (greeter->priv->authentication_session, response);
368         free (response);
369     }
370 }
371
372 static void
373 send_end_authentication (Greeter *greeter, guint32 sequence_number, const gchar *username, int result)
374 {
375     guint8 message[MAX_MESSAGE_LENGTH];
376     gsize offset = 0;
377
378     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_END_AUTHENTICATION, int_length () + string_length (username) + int_length (), &offset);
379     write_int (message, MAX_MESSAGE_LENGTH, sequence_number, &offset);
380     write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
381     write_int (message, MAX_MESSAGE_LENGTH, result, &offset);
382     write_message (greeter, message, offset);
383 }
384
385 void
386 greeter_idle (Greeter *greeter)
387 {
388     guint8 message[MAX_MESSAGE_LENGTH];
389     gsize offset = 0;
390
391     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_IDLE, 0, &offset);
392     write_message (greeter, message, offset);
393 }
394
395 void
396 greeter_reset (Greeter *greeter)
397 {
398     guint8 message[MAX_MESSAGE_LENGTH];
399     gsize offset = 0;
400     guint32 length = 0;
401     GHashTableIter iter;
402     gpointer key, value;
403
404     g_return_if_fail (greeter != NULL);
405
406     g_hash_table_iter_init (&iter, greeter->priv->hints);
407     while (g_hash_table_iter_next (&iter, &key, &value))
408         length += string_length (key) + string_length (value);
409
410     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_RESET, length, &offset);
411     g_hash_table_iter_init (&iter, greeter->priv->hints);
412     while (g_hash_table_iter_next (&iter, &key, &value))
413     {
414         write_string (message, MAX_MESSAGE_LENGTH, key, &offset);
415         write_string (message, MAX_MESSAGE_LENGTH, value, &offset);
416     }
417     write_message (greeter, message, offset);
418 }
419
420 static void
421 authentication_complete_cb (Session *session, Greeter *greeter)
422 {
423     int result;
424
425     g_debug ("Authenticate result for user %s: %s", session_get_username (session), session_get_authentication_result_string (session));
426
427     result = session_get_authentication_result (session);
428     if (session_get_is_authenticated (session))
429     {
430         if (session_get_user (session))
431             g_debug ("User %s authorized", session_get_username (session));
432         else
433         {
434             g_debug ("User %s authorized, but no account of that name exists", session_get_username (session));
435             result = PAM_USER_UNKNOWN;
436         }
437     }
438
439     send_end_authentication (greeter, greeter->priv->authentication_sequence_number, session_get_username (session), result);
440 }
441
442 static void
443 reset_session (Greeter *greeter)
444 {
445     g_free (greeter->priv->remote_session);
446     greeter->priv->remote_session = NULL;
447     if (greeter->priv->authentication_session)
448     {
449         g_signal_handlers_disconnect_matched (greeter->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, greeter);
450         session_stop (greeter->priv->authentication_session);
451         g_clear_object (&greeter->priv->authentication_session);
452     }
453
454     greeter->priv->guest_account_authenticated = FALSE;
455 }
456
457 static void
458 handle_login (Greeter *greeter, guint32 sequence_number, const gchar *username)
459 {
460     const gchar *autologin_username, *service;
461     gboolean is_interactive;
462
463     if (username[0] == '\0')
464     {
465         g_debug ("Greeter start authentication");
466         username = NULL;
467     }
468     else
469         g_debug ("Greeter start authentication for %s", username);
470
471     reset_session (greeter);
472
473     if (greeter->priv->active_username)
474         g_free (greeter->priv->active_username);
475     greeter->priv->active_username = g_strdup (username);
476     g_object_notify (G_OBJECT (greeter), GREETER_PROPERTY_ACTIVE_USERNAME);
477
478     greeter->priv->authentication_sequence_number = sequence_number;
479     g_signal_emit (greeter, signals[CREATE_SESSION], 0, &greeter->priv->authentication_session);
480     if (!greeter->priv->authentication_session)
481     {
482         send_end_authentication (greeter, sequence_number, "", PAM_USER_UNKNOWN);
483         return;
484     }
485
486     g_signal_connect (G_OBJECT (greeter->priv->authentication_session), SESSION_SIGNAL_GOT_MESSAGES, G_CALLBACK (pam_messages_cb), greeter);
487     g_signal_connect (G_OBJECT (greeter->priv->authentication_session), SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (authentication_complete_cb), greeter);
488
489     /* Use non-interactive service for autologin user */
490     autologin_username = g_hash_table_lookup (greeter->priv->hints, "autologin-user");
491     if (autologin_username != NULL && g_strcmp0 (username, autologin_username) == 0)
492     {
493         service = greeter->priv->autologin_pam_service;
494         is_interactive = FALSE;
495     }
496     else
497     {
498         service = greeter->priv->pam_service;
499         is_interactive = TRUE;
500     }
501
502     /* Run the session process */
503     session_set_pam_service (greeter->priv->authentication_session, service);
504     session_set_username (greeter->priv->authentication_session, username);
505     session_set_do_authenticate (greeter->priv->authentication_session, TRUE);
506     session_set_is_interactive (greeter->priv->authentication_session, is_interactive);
507     session_start (greeter->priv->authentication_session);
508 }
509
510 static void
511 handle_login_as_guest (Greeter *greeter, guint32 sequence_number)
512 {
513     g_debug ("Greeter start authentication for guest account");
514
515     reset_session (greeter);
516
517     if (!greeter->priv->allow_guest)
518     {
519         g_debug ("Guest account is disabled");
520         send_end_authentication (greeter, sequence_number, "", PAM_USER_UNKNOWN);
521         return;
522     }
523
524     greeter->priv->guest_account_authenticated = TRUE;
525     send_end_authentication (greeter, sequence_number, "", PAM_SUCCESS);
526 }
527
528 static gchar *
529 get_remote_session_service (const gchar *session_name)
530 {
531     GKeyFile *session_desktop_file;
532     gboolean result;
533     const gchar *c;
534     gchar *remote_sessions_dir, *filename, *path, *service = NULL;
535     GError *error = NULL;
536
537     /* Validate session name doesn't contain directory separators */
538     for (c = session_name; *c; c++)
539     {
540         if (*c == '/')
541             return NULL;
542     }
543
544     /* Load the session file */
545     session_desktop_file = g_key_file_new ();
546     filename = g_strdup_printf ("%s.desktop", session_name);
547     remote_sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
548     path = g_build_filename (remote_sessions_dir, filename, NULL);
549     g_free (remote_sessions_dir);
550     g_free (filename);
551     result = g_key_file_load_from_file (session_desktop_file, path, G_KEY_FILE_NONE, &error);
552     if (error)
553         g_debug ("Failed to load session file %s: %s", path, error->message);
554     g_free (path);
555     g_clear_error (&error);
556     if (result)
557         service = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, "X-LightDM-PAM-Service", NULL);
558     g_key_file_free (session_desktop_file);
559
560     return service;
561 }
562
563 static void
564 handle_login_remote (Greeter *greeter, const gchar *session_name, const gchar *username, guint32 sequence_number)
565 {
566     gchar *service;
567
568     if (username[0] == '\0')
569     {
570         g_debug ("Greeter start authentication for remote session %s", session_name);
571         username = NULL;
572     }
573     else
574         g_debug ("Greeter start authentication for remote session %s as user %s", session_name, username);
575
576     reset_session (greeter);
577
578     service = get_remote_session_service (session_name);
579     if (!service)
580     {
581         send_end_authentication (greeter, sequence_number, "", PAM_SYSTEM_ERR);
582         return;
583     }
584
585     greeter->priv->authentication_sequence_number = sequence_number;
586     greeter->priv->remote_session = g_strdup (session_name);
587     g_signal_emit (greeter, signals[CREATE_SESSION], 0, &greeter->priv->authentication_session);
588     if (greeter->priv->authentication_session)
589     {
590         g_signal_connect (G_OBJECT (greeter->priv->authentication_session), SESSION_SIGNAL_GOT_MESSAGES, G_CALLBACK (pam_messages_cb), greeter);
591         g_signal_connect (G_OBJECT (greeter->priv->authentication_session), SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (authentication_complete_cb), greeter);
592
593         /* Run the session process */
594         session_set_pam_service (greeter->priv->authentication_session, service);
595         session_set_username (greeter->priv->authentication_session, username);
596         session_set_do_authenticate (greeter->priv->authentication_session, TRUE);
597         session_set_is_interactive (greeter->priv->authentication_session, TRUE);
598         session_set_is_guest (greeter->priv->authentication_session, TRUE);
599         session_start (greeter->priv->authentication_session);
600     }
601
602     g_free (service);
603
604     if (!greeter->priv->authentication_session)
605     {
606         send_end_authentication (greeter, sequence_number, "", PAM_USER_UNKNOWN);
607         return;
608     }
609 }
610
611 static void
612 handle_continue_authentication (Greeter *greeter, gchar **secrets)
613 {
614     int messages_length;
615     const struct pam_message *messages;
616     struct pam_response *response;
617     int i, j, n_prompts = 0;
618
619     /* Not in authentication */
620     if (greeter->priv->authentication_session == NULL)
621         return;
622
623     messages_length = session_get_messages_length (greeter->priv->authentication_session);
624     messages = session_get_messages (greeter->priv->authentication_session);
625
626     /* Check correct number of responses */
627     for (i = 0; i < messages_length; i++)
628     {
629         int msg_style = messages[i].msg_style;
630         if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
631             n_prompts++;
632     }
633     if (g_strv_length (secrets) != n_prompts)
634     {
635         session_respond_error (greeter->priv->authentication_session, PAM_CONV_ERR);
636         return;
637     }
638
639     g_debug ("Continue authentication");
640
641     /* Build response */
642     response = calloc (messages_length, sizeof (struct pam_response));
643     for (i = 0, j = 0; i < messages_length; i++)
644     {
645         int msg_style = messages[i].msg_style;
646         if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
647         {
648             size_t secret_length = strlen (secrets[j]) + 1;
649             response[i].resp = secure_malloc (greeter, secret_length);
650             memcpy (response[i].resp, secrets[j], secret_length); // FIXME: Need to convert from UTF-8
651             j++;
652         }
653     }
654
655     session_respond (greeter->priv->authentication_session, response);
656
657     for (i = 0; i < messages_length; i++)
658         secure_free (greeter, response[i].resp);
659     free (response);
660 }
661
662 static void
663 handle_cancel_authentication (Greeter *greeter)
664 {
665     /* Not in authentication */
666     if (greeter->priv->authentication_session == NULL)
667         return;
668
669     g_debug ("Cancel authentication");
670     reset_session (greeter);
671 }
672
673 static void
674 handle_start_session (Greeter *greeter, const gchar *session)
675 {
676     gboolean result;
677     guint8 message[MAX_MESSAGE_LENGTH];
678     gsize offset = 0;
679     SessionType session_type = SESSION_TYPE_LOCAL;
680
681     if (strcmp (session, "") == 0)
682         session = NULL;
683
684     /* Use session type chosen in remote session */
685     if (greeter->priv->remote_session)
686     {
687         session_type = SESSION_TYPE_REMOTE;
688         session = greeter->priv->remote_session;
689     }
690
691     if (greeter->priv->guest_account_authenticated || session_get_is_authenticated (greeter->priv->authentication_session))
692     {
693         if (session)
694             g_debug ("Greeter requests session %s", session);
695         else
696             g_debug ("Greeter requests default session");
697         greeter->priv->start_session = TRUE;
698         g_signal_emit (greeter, signals[START_SESSION], 0, session_type, session, &result);
699     }
700     else
701     {
702         g_debug ("Ignoring start session request, user is not authorized");
703         result = FALSE;
704     }
705
706     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_SESSION_RESULT, int_length (), &offset);
707     write_int (message, MAX_MESSAGE_LENGTH, result ? 0 : 1, &offset);
708     write_message (greeter, message, offset);
709 }
710
711 static void
712 handle_set_language (Greeter *greeter, const gchar *language)
713 {
714     User *user;
715
716     if (!greeter->priv->guest_account_authenticated && !session_get_is_authenticated (greeter->priv->authentication_session))
717     {
718         g_debug ("Ignoring set language request, user is not authorized");
719         return;
720     }
721
722     // FIXME: Could use this
723     if (greeter->priv->guest_account_authenticated)
724     {
725         g_debug ("Ignoring set language request for guest user");
726         return;
727     }
728
729     g_debug ("Greeter sets language %s", language);
730     user = session_get_user (greeter->priv->authentication_session);
731     user_set_language (user, language);
732 }
733
734 static void
735 handle_ensure_shared_dir (Greeter *greeter, const gchar *username)
736 {
737     gchar *dir;
738     guint8 message[MAX_MESSAGE_LENGTH];
739     gsize offset = 0;
740
741     g_debug ("Greeter requests data directory for user %s", username);
742
743     dir = shared_data_manager_ensure_user_dir (shared_data_manager_get_instance (), username);
744
745     write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_SHARED_DIR_RESULT, string_length (dir), &offset);
746     write_string (message, MAX_MESSAGE_LENGTH, dir, &offset);
747     write_message (greeter, message, offset);
748
749     g_free (dir);
750 }
751
752 static guint32
753 read_int (Greeter *greeter, gsize *offset)
754 {
755     guint32 value;
756     guint8 *buffer;
757     if (greeter->priv->n_read - *offset < sizeof (guint32))
758     {
759         g_warning ("Not enough space for int, need %zu, got %zu", sizeof (guint32), greeter->priv->n_read - *offset);
760         return 0;
761     }
762     buffer = greeter->priv->read_buffer + *offset;
763     value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
764     *offset += int_length ();
765     return value;
766 }
767
768 static int
769 get_message_length (Greeter *greeter)
770 {
771     gsize offset;
772     int payload_length;
773
774     offset = int_length ();
775     payload_length = read_int (greeter, &offset);
776
777     if (HEADER_SIZE + payload_length < HEADER_SIZE)
778     {
779         g_warning ("Payload length of %u octets too long", payload_length);
780         return HEADER_SIZE;
781     }
782
783     return HEADER_SIZE + payload_length;
784 }
785
786 static gchar *
787 read_string_full (Greeter *greeter, gsize *offset, void* (*alloc_fn)(size_t n))
788 {
789     guint32 length;
790     gchar *value;
791
792     length = read_int (greeter, offset);
793     if (greeter->priv->n_read - *offset < length)
794     {
795         g_warning ("Not enough space for string, need %u, got %zu", length, greeter->priv->n_read - *offset);
796         return g_strdup ("");
797     }
798
799     value = (*alloc_fn) (sizeof (gchar) * (length + 1));
800     memcpy (value, greeter->priv->read_buffer + *offset, length);
801     value[length] = '\0';
802     *offset += length;
803
804     return value;
805 }
806
807 static gchar *
808 read_string (Greeter *greeter, gsize *offset)
809 {
810     return read_string_full (greeter, offset, g_malloc);
811 }
812
813 static gchar *
814 read_secret (Greeter *greeter, gsize *offset)
815 {
816     if (greeter->priv->use_secure_memory)
817         return read_string_full (greeter, offset, gcry_malloc_secure);
818     else
819         return read_string_full (greeter, offset, g_malloc);
820 }
821
822 static gboolean
823 read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
824 {
825     Greeter *greeter = data;
826     gsize n_to_read, n_read, offset;
827     GIOStatus status;
828     int id, length, i;
829     guint32 sequence_number, n_secrets, max_secrets;
830     gchar *version, *username, *session_name, *language;
831     gchar **secrets;
832     gboolean resettable = FALSE;
833     GError *error = NULL;
834
835     if (condition == G_IO_HUP)
836     {
837         g_debug ("Greeter closed communication channel");
838         greeter->priv->from_greeter_watch = 0;
839         return FALSE;
840     }
841
842     n_to_read = HEADER_SIZE;
843     if (greeter->priv->n_read >= HEADER_SIZE)
844     {
845         n_to_read = get_message_length (greeter);
846         if (n_to_read <= HEADER_SIZE)
847         {
848             greeter->priv->from_greeter_watch = 0;
849             return FALSE;
850         }
851     }
852
853     status = g_io_channel_read_chars (greeter->priv->from_greeter_channel,
854                                       (gchar *) greeter->priv->read_buffer + greeter->priv->n_read,
855                                       n_to_read - greeter->priv->n_read,
856                                       &n_read,
857                                       &error);
858     if (error)
859         g_warning ("Error reading from greeter: %s", error->message);
860     g_clear_error (&error);
861     if (status != G_IO_STATUS_NORMAL)
862         return TRUE;
863
864     greeter->priv->n_read += n_read;
865     if (greeter->priv->n_read != n_to_read)
866         return TRUE;
867
868     /* If have header, rerun for content */
869     if (greeter->priv->n_read == HEADER_SIZE)
870     {
871         n_to_read = get_message_length (greeter);
872         if (n_to_read > HEADER_SIZE)
873         {
874             greeter->priv->read_buffer = secure_realloc (greeter, greeter->priv->read_buffer, n_to_read);
875             read_cb (source, condition, greeter);
876             return TRUE;
877         }
878     }
879
880     offset = 0;
881     id = read_int (greeter, &offset);
882     length = HEADER_SIZE + read_int (greeter, &offset);
883     switch (id)
884     {
885     case GREETER_MESSAGE_CONNECT:
886         version = read_string (greeter, &offset);
887         if (offset < length)
888             resettable = read_int (greeter, &offset) != 0;
889         handle_connect (greeter, version, resettable);
890         g_free (version);
891         break;
892     case GREETER_MESSAGE_AUTHENTICATE:
893         sequence_number = read_int (greeter, &offset);
894         username = read_string (greeter, &offset);
895         handle_login (greeter, sequence_number, username);
896         g_free (username);
897         break;
898     case GREETER_MESSAGE_AUTHENTICATE_AS_GUEST:
899         sequence_number = read_int (greeter, &offset);
900         handle_login_as_guest (greeter, sequence_number);
901         break;
902     case GREETER_MESSAGE_AUTHENTICATE_REMOTE:
903         sequence_number = read_int (greeter, &offset);
904         session_name = read_string (greeter, &offset);
905         username = read_string (greeter, &offset);
906         handle_login_remote (greeter, session_name, username, sequence_number);
907         break;
908     case GREETER_MESSAGE_CONTINUE_AUTHENTICATION:
909         n_secrets = read_int (greeter, &offset);
910         max_secrets = (G_MAXUINT32 - 1) / sizeof (gchar *);
911         if (n_secrets > max_secrets)
912         {
913             g_warning ("Array length of %u elements too long", n_secrets);
914             greeter->priv->from_greeter_watch = 0;
915             return FALSE;
916         }
917         secrets = g_malloc (sizeof (gchar *) * (n_secrets + 1));
918         for (i = 0; i < n_secrets; i++)
919             secrets[i] = read_secret (greeter, &offset);
920         secrets[i] = NULL;
921         handle_continue_authentication (greeter, secrets);
922         for (i = 0; i < n_secrets; i++)
923             secure_free (greeter, secrets[i]);
924         g_free (secrets);
925         break;
926     case GREETER_MESSAGE_CANCEL_AUTHENTICATION:
927         handle_cancel_authentication (greeter);
928         break;
929     case GREETER_MESSAGE_START_SESSION:
930         session_name = read_string (greeter, &offset);
931         handle_start_session (greeter, session_name);
932         g_free (session_name);
933         break;
934     case GREETER_MESSAGE_SET_LANGUAGE:
935         language = read_string (greeter, &offset);
936         handle_set_language (greeter, language);
937         g_free (language);
938         break;
939     case GREETER_MESSAGE_ENSURE_SHARED_DIR:
940         username = read_string (greeter, &offset);
941         handle_ensure_shared_dir (greeter, username);
942         g_free (username);
943         break;
944     default:
945         g_warning ("Unknown message from greeter: %d", id);
946         break;
947     }
948
949     greeter->priv->n_read = 0;
950
951     return TRUE;
952 }
953
954 gboolean
955 greeter_get_guest_authenticated (Greeter *greeter)
956 {
957     g_return_val_if_fail (greeter != NULL, FALSE);
958     return greeter->priv->guest_account_authenticated;
959 }
960
961 Session *
962 greeter_get_authentication_session (Greeter *greeter)
963 {
964     g_return_val_if_fail (greeter != NULL, NULL);
965     return greeter->priv->authentication_session;
966 }
967
968 gboolean
969 greeter_get_resettable (Greeter *greeter)
970 {
971     g_return_val_if_fail (greeter != NULL, FALSE);
972     return greeter->priv->resettable;
973 }
974
975 gboolean
976 greeter_get_start_session (Greeter *greeter)
977 {
978     g_return_val_if_fail (greeter != NULL, FALSE);
979     return greeter->priv->start_session;
980 }
981
982 const gchar *
983 greeter_get_active_username (Greeter *greeter)
984 {
985     g_return_val_if_fail (greeter != NULL, NULL);
986     return greeter->priv->active_username;
987 }
988
989 static Session *
990 greeter_real_create_session (Greeter *greeter)
991 {
992     return NULL;
993 }
994
995 static gboolean
996 greeter_real_start_session (Greeter *greeter, SessionType type, const gchar *session)
997 {
998     return FALSE;
999 }
1000
1001 static void
1002 greeter_init (Greeter *greeter)
1003 {
1004     greeter->priv = G_TYPE_INSTANCE_GET_PRIVATE (greeter, GREETER_TYPE, GreeterPrivate);
1005     greeter->priv->read_buffer = secure_malloc (greeter, HEADER_SIZE);
1006     greeter->priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1007     greeter->priv->use_secure_memory = config_get_boolean (config_get_instance (), "LightDM", "lock-memory");
1008     greeter->priv->to_greeter_input = -1;
1009     greeter->priv->from_greeter_output = -1;
1010 }
1011
1012 static void
1013 greeter_finalize (GObject *object)
1014 {
1015     Greeter *self = GREETER (object);
1016
1017     g_free (self->priv->pam_service);
1018     g_free (self->priv->autologin_pam_service);
1019     secure_free (self, self->priv->read_buffer);
1020     g_hash_table_unref (self->priv->hints);
1021     g_free (self->priv->remote_session);
1022     g_free (self->priv->active_username);
1023     if (self->priv->authentication_session)
1024     {
1025         g_signal_handlers_disconnect_matched (self->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1026         g_object_unref (self->priv->authentication_session);
1027     }
1028     close (self->priv->to_greeter_input);
1029     close (self->priv->from_greeter_output);
1030     if (self->priv->to_greeter_channel)
1031         g_io_channel_unref (self->priv->to_greeter_channel);
1032     if (self->priv->from_greeter_channel)
1033         g_io_channel_unref (self->priv->from_greeter_channel);
1034     if (self->priv->from_greeter_watch)
1035         g_source_remove (self->priv->from_greeter_watch);
1036
1037     G_OBJECT_CLASS (greeter_parent_class)->finalize (object);
1038 }
1039
1040 static void
1041 greeter_set_property (GObject      *object,
1042                       guint         prop_id,
1043                       const GValue *value,
1044                       GParamSpec   *pspec)
1045 {
1046     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1047 }
1048
1049 static void
1050 greeter_get_property (GObject    *object,
1051                       guint       prop_id,
1052                       GValue     *value,
1053                       GParamSpec *pspec)
1054 {
1055     Greeter *greeter = GREETER (object);
1056
1057     switch (prop_id) {
1058     case PROP_ACTIVE_USERNAME:
1059         g_value_set_string (value, greeter_get_active_username (greeter));
1060         break;
1061     default:
1062         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1063         break;
1064     }
1065 }
1066
1067 static void
1068 greeter_class_init (GreeterClass *klass)
1069 {
1070     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1071
1072     klass->create_session = greeter_real_create_session;
1073     klass->start_session = greeter_real_start_session;
1074     object_class->finalize = greeter_finalize;
1075     object_class->get_property = greeter_get_property;
1076     object_class->set_property = greeter_set_property;
1077
1078     signals[CONNECTED] =
1079         g_signal_new (GREETER_SIGNAL_CONNECTED,
1080                       G_TYPE_FROM_CLASS (klass),
1081                       G_SIGNAL_RUN_LAST,
1082                       G_STRUCT_OFFSET (GreeterClass, connected),
1083                       NULL, NULL,
1084                       NULL,
1085                       G_TYPE_NONE, 0);
1086
1087     signals[CREATE_SESSION] =
1088         g_signal_new (GREETER_SIGNAL_CREATE_SESSION,
1089                       G_TYPE_FROM_CLASS (klass),
1090                       G_SIGNAL_RUN_LAST,
1091                       G_STRUCT_OFFSET (GreeterClass, create_session),
1092                       g_signal_accumulator_first_wins,
1093                       NULL,
1094                       NULL,
1095                       SESSION_TYPE, 0);
1096
1097     signals[START_SESSION] =
1098         g_signal_new (GREETER_SIGNAL_START_SESSION,
1099                       G_TYPE_FROM_CLASS (klass),
1100                       G_SIGNAL_RUN_LAST,
1101                       G_STRUCT_OFFSET (GreeterClass, start_session),
1102                       g_signal_accumulator_true_handled,
1103                       NULL,
1104                       NULL,
1105                       G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_STRING);
1106
1107     g_object_class_install_property (object_class,
1108                                      PROP_ACTIVE_USERNAME,
1109                                      g_param_spec_string (GREETER_PROPERTY_ACTIVE_USERNAME,
1110                                                           GREETER_PROPERTY_ACTIVE_USERNAME,
1111                                                           "Active username",
1112                                                           NULL,
1113                                                           G_PARAM_READABLE));
1114
1115     g_type_class_add_private (klass, sizeof (GreeterPrivate));
1116 }