2 * Copyright (C) 2010 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
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 3 of the License, or (at your option) any
8 * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
15 #include <sys/utsname.h>
17 #include <gio/gdesktopappinfo.h>
18 #include <security/pam_appl.h>
19 #include <libxklavier/xklavier.h>
22 #include "greeter-protocol.h"
29 PROP_DEFAULT_LANGUAGE,
34 PROP_TIMED_LOGIN_USER,
35 PROP_TIMED_LOGIN_DELAY,
36 PROP_AUTHENTICATION_USER,
37 PROP_IN_AUTHENTICATION,
38 PROP_IS_AUTHENTICATED,
50 AUTHENTICATION_COMPLETE,
55 static guint signals[LAST_SIGNAL] = { 0 };
57 struct _LdmGreeterPrivate
59 GDBusConnection *lightdm_bus;
61 GDBusConnection *system_bus;
63 GDBusProxy *session_proxy, *user_proxy;
65 GIOChannel *to_server_channel, *from_server_channel;
79 gboolean have_languages;
82 gchar *default_layout;
83 XklEngine *xkl_engine;
84 XklConfigRec *xkl_config;
85 gboolean have_layouts;
89 gboolean have_sessions;
91 gchar *default_session;
93 gchar *authentication_user;
94 gboolean in_authentication;
95 gboolean is_authenticated;
102 G_DEFINE_TYPE (LdmGreeter, ldm_greeter, G_TYPE_OBJECT);
104 #define HEADER_SIZE 8
109 * Create a new greeter.
111 * Return value: the new #LdmGreeter
116 return g_object_new (LDM_TYPE_GREETER, NULL);
120 timed_login_cb (gpointer data)
122 LdmGreeter *greeter = data;
124 greeter->priv->login_timeout = 0;
125 g_signal_emit (G_OBJECT (greeter), signals[TIMED_LOGIN], 0, greeter->priv->timed_user);
137 write_int (LdmGreeter *greeter, guint32 value)
140 buffer[0] = value >> 24;
141 buffer[1] = (value >> 16) & 0xFF;
142 buffer[2] = (value >> 8) & 0xFF;
143 buffer[3] = value & 0xFF;
144 if (g_io_channel_write_chars (greeter->priv->to_server_channel, buffer, int_length (), NULL, NULL) != G_IO_STATUS_NORMAL)
145 g_warning ("Error writing to server");
149 write_string (LdmGreeter *greeter, const gchar *value)
151 write_int (greeter, strlen (value));
152 g_io_channel_write_chars (greeter->priv->to_server_channel, value, -1, NULL, NULL);
156 read_int (LdmGreeter *greeter, gsize *offset)
160 if (greeter->priv->n_read - *offset < int_length ())
162 g_warning ("Not enough space for int, need %i, got %zi", int_length (), greeter->priv->n_read - *offset);
165 buffer = greeter->priv->read_buffer + *offset;
166 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
167 *offset += int_length ();
172 read_string (LdmGreeter *greeter, gsize *offset)
177 length = read_int (greeter, offset);
178 if (greeter->priv->n_read - *offset < length)
180 g_warning ("Not enough space for string, need %u, got %zu", length, greeter->priv->n_read - *offset);
181 return g_strdup ("");
184 value = g_malloc (sizeof (gchar) * (length + 1));
185 memcpy (value, greeter->priv->read_buffer + *offset, length);
186 value[length] = '\0';
193 string_length (const gchar *value)
195 return int_length () + strlen (value);
199 write_header (LdmGreeter *greeter, guint32 id, guint32 length)
201 write_int (greeter, id);
202 write_int (greeter, length);
205 static guint32 get_packet_length (LdmGreeter *greeter)
208 return read_int (greeter, &offset);
212 flush (LdmGreeter *greeter)
214 g_io_channel_flush (greeter->priv->to_server_channel, NULL);
218 handle_prompt_authentication (LdmGreeter *greeter, gsize *offset)
222 n_messages = read_int (greeter, offset);
223 g_debug ("Prompt user with %d message(s)", n_messages);
225 for (i = 0; i < n_messages; i++)
230 msg_style = read_int (greeter, offset);
231 msg = read_string (greeter, offset);
233 // FIXME: Should stop on prompts?
236 case PAM_PROMPT_ECHO_OFF:
237 case PAM_PROMPT_ECHO_ON:
238 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, msg);
241 g_signal_emit (G_OBJECT (greeter), signals[SHOW_ERROR], 0, msg);
244 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, msg);
253 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
255 LdmGreeter *greeter = data;
256 gsize n_to_read, n_read, offset;
258 guint32 id, return_code;
259 GError *error = NULL;
261 n_to_read = HEADER_SIZE;
262 if (greeter->priv->n_read >= HEADER_SIZE)
263 n_to_read += get_packet_length (greeter);
265 status = g_io_channel_read_chars (greeter->priv->from_server_channel,
266 greeter->priv->read_buffer + greeter->priv->n_read,
267 n_to_read - greeter->priv->n_read,
270 if (status != G_IO_STATUS_NORMAL)
271 g_warning ("Error reading from server: %s", error->message);
272 g_clear_error (&error);
273 if (status != G_IO_STATUS_NORMAL)
276 greeter->priv->n_read += n_read;
277 if (greeter->priv->n_read != n_to_read)
280 /* If have header, rerun for content */
281 if (greeter->priv->n_read == HEADER_SIZE)
283 n_to_read = get_packet_length (greeter);
286 greeter->priv->read_buffer = g_realloc (greeter->priv->read_buffer, HEADER_SIZE + n_to_read);
287 return from_server_cb (source, condition, data);
292 id = read_int (greeter, &offset);
293 read_int (greeter, &offset);
296 case GREETER_MESSAGE_CONNECTED:
297 greeter->priv->theme = read_string (greeter, &offset);
298 greeter->priv->default_layout = read_string (greeter, &offset);
299 greeter->priv->default_session = read_string (greeter, &offset);
300 greeter->priv->timed_user = read_string (greeter, &offset);
301 greeter->priv->login_delay = read_int (greeter, &offset);
303 g_debug ("Connected theme=%s default-layout=%s default-session=%s timed-user=%s login-delay=%d",
304 greeter->priv->theme,
305 greeter->priv->default_layout, greeter->priv->default_session,
306 greeter->priv->timed_user, greeter->priv->login_delay);
308 /* Set timeout for default login */
309 if (greeter->priv->timed_user[0] != '\0' && greeter->priv->login_delay > 0)
311 g_debug ("Logging in as %s in %d seconds", greeter->priv->timed_user, greeter->priv->login_delay);
312 greeter->priv->login_timeout = g_timeout_add (greeter->priv->login_delay * 1000, timed_login_cb, greeter);
314 g_signal_emit (G_OBJECT (greeter), signals[CONNECTED], 0);
316 case GREETER_MESSAGE_QUIT:
317 g_debug ("Got quit request from server");
318 g_signal_emit (G_OBJECT (greeter), signals[QUIT], 0);
320 case GREETER_MESSAGE_PROMPT_AUTHENTICATION:
321 handle_prompt_authentication (greeter, &offset);
323 case GREETER_MESSAGE_END_AUTHENTICATION:
324 return_code = read_int (greeter, &offset);
325 g_debug ("Authentication complete with return code %d", return_code);
326 greeter->priv->is_authenticated = (return_code == 0);
327 if (!greeter->priv->is_authenticated)
329 g_free (greeter->priv->authentication_user);
330 greeter->priv->authentication_user = NULL;
332 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
335 g_warning ("Unknown message from server: %d", id);
339 greeter->priv->n_read = 0;
345 * ldm_greeter_connect_to_server:
346 * @greeter: The greeter to connect
348 * Connects the greeter to the display manager.
350 * Return value: TRUE if successfully connected
353 ldm_greeter_connect_to_server (LdmGreeter *greeter)
355 GError *error = NULL;
356 const gchar *bus_address, *fd;
357 GBusType bus_type = G_BUS_TYPE_SYSTEM;
359 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
361 greeter->priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
362 if (!greeter->priv->system_bus)
363 g_warning ("Failed to connect to system bus: %s", error->message);
364 g_clear_error (&error);
365 if (!greeter->priv->system_bus)
368 bus_address = getenv ("LDM_BUS");
369 if (bus_address && strcmp (bus_address, "SESSION") == 0)
370 bus_type = G_BUS_TYPE_SESSION;
372 greeter->priv->lightdm_bus = g_bus_get_sync (bus_type, NULL, &error);
373 if (!greeter->priv->lightdm_bus)
374 g_warning ("Failed to connect to LightDM bus: %s", error->message);
375 g_clear_error (&error);
376 if (!greeter->priv->lightdm_bus)
379 fd = getenv ("LDM_TO_SERVER_FD");
382 g_warning ("No LDM_TO_SERVER_FD environment variable");
385 greeter->priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
386 g_io_channel_set_encoding (greeter->priv->to_server_channel, NULL, NULL);
388 fd = getenv ("LDM_FROM_SERVER_FD");
391 g_warning ("No LDM_FROM_SERVER_FD environment variable");
394 greeter->priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
395 g_io_channel_set_encoding (greeter->priv->from_server_channel, NULL, NULL);
396 g_io_add_watch (greeter->priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
398 greeter->priv->session_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
399 G_DBUS_PROXY_FLAGS_NONE,
401 "org.lightdm.LightDisplayManager",
402 "/org/lightdm/LightDisplayManager/Session",
403 "org.lightdm.LightDisplayManager.Session",
405 greeter->priv->user_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
406 G_DBUS_PROXY_FLAGS_NONE,
408 "org.lightdm.LightDisplayManager",
409 "/org/lightdm/LightDisplayManager/Users",
410 "org.lightdm.LightDisplayManager.Users",
413 g_debug ("Connecting to display manager...");
414 write_header (greeter, GREETER_MESSAGE_CONNECT, 0);
421 * ldm_greeter_get_hostname:
422 * @greeter: a #LdmGreeter
424 * Return value: The host this greeter is displaying
427 ldm_greeter_get_hostname (LdmGreeter *greeter)
429 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
431 if (!greeter->priv->hostname)
435 greeter->priv->hostname = g_strdup (info.nodename);
438 return greeter->priv->hostname;
442 * ldm_greeter_get_theme:
443 * @greeter: a #LdmGreeter
445 * Return value: The theme this greeter is using
448 ldm_greeter_get_theme (LdmGreeter *greeter)
450 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
451 return greeter->priv->theme;
455 load_theme (LdmGreeter *greeter)
457 GError *error = NULL;
459 if (greeter->priv->theme_file)
462 greeter->priv->theme_file = g_key_file_new ();
463 if (!g_key_file_load_from_file (greeter->priv->theme_file, greeter->priv->theme, G_KEY_FILE_NONE, &error))
464 g_warning ("Failed to read theme file: %s", error->message);
465 g_clear_error (&error);
469 * ldm_greeter_get_string_property:
470 * @greeter: a #LdmGreeter
471 * @name: the name of the property to get
473 * Return value: The value of this property or NULL if it is not defined
476 ldm_greeter_get_string_property (LdmGreeter *greeter, const gchar *name)
478 GError *error = NULL;
481 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
482 g_return_val_if_fail (name != NULL, NULL);
484 load_theme (greeter);
486 result = g_key_file_get_string (greeter->priv->theme_file, "theme", name, &error);
488 g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
489 g_clear_error (&error);
495 * ldm_greeter_get_integer_property:
496 * @greeter: a #LdmGreeter
497 * @name: the name of the property to get
499 * Return value: The value of this property or 0 if it is not defined
502 ldm_greeter_get_integer_property (LdmGreeter *greeter, const gchar *name)
504 GError *error = NULL;
507 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
508 g_return_val_if_fail (name != NULL, 0);
510 load_theme (greeter);
512 result = g_key_file_get_integer (greeter->priv->theme_file, "theme", name, &error);
514 g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
515 g_clear_error (&error);
521 * ldm_greeter_get_boolean_property:
522 * @greeter: a #LdmGreeter
523 * @name: the name of the property to get
525 * Return value: The value of this property or FALSE if it is not defined
528 ldm_greeter_get_boolean_property (LdmGreeter *greeter, const gchar *name)
530 GError *error = NULL;
533 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
534 g_return_val_if_fail (name != NULL, FALSE);
536 load_theme (greeter);
538 result = g_key_file_get_boolean (greeter->priv->theme_file, "theme", name, &error);
540 g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
541 g_clear_error (&error);
547 update_users (LdmGreeter *greeter)
549 GVariant *result, *user_array;
551 gchar *name, *real_name, *image;
553 GError *error = NULL;
555 if (greeter->priv->have_users)
558 g_debug ("Getting user list...");
559 result = g_dbus_proxy_call_sync (greeter->priv->user_proxy,
562 G_DBUS_CALL_FLAGS_NONE,
567 g_warning ("Failed to get users: %s", error->message);
568 g_clear_error (&error);
572 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(a(sssb))")))
574 g_warning ("Unknown type returned");
575 g_variant_unref (result);
578 user_array = g_variant_get_child_value (result, 0);
579 g_debug ("Got %zi users", g_variant_n_children (user_array));
580 g_variant_iter_init (&iter, user_array);
581 while (g_variant_iter_next (&iter, "(&s&s&sb)", &name, &real_name, &image, &logged_in))
585 user = ldm_user_new (greeter, name, real_name, image, logged_in);
586 greeter->priv->users = g_list_append (greeter->priv->users, user);
588 greeter->priv->have_users = TRUE;
590 g_variant_unref (result);
594 * ldm_greeter_get_num_users:
595 * @greeter: a #LdmGreeter
597 * Return value: The number of users able to log in
600 ldm_greeter_get_num_users (LdmGreeter *greeter)
602 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
603 update_users (greeter);
604 return g_list_length (greeter->priv->users);
608 * ldm_greeter_get_users:
609 * @greeter: A #LdmGreeter
611 * Get a list of users to present to the user. This list may be a subset of the
612 * available users and may be empty depending on the server configuration.
614 * Return value: (element-type LdmUser): A list of #LdmUser that should be presented to the user.
617 ldm_greeter_get_users (LdmGreeter *greeter)
619 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
620 update_users (greeter);
621 return greeter->priv->users;
625 update_languages (LdmGreeter *greeter)
627 gchar *stdout_text = NULL, *stderr_text = NULL;
630 GError *error = NULL;
632 if (greeter->priv->have_languages)
635 result = g_spawn_command_line_sync ("locale -a", &stdout_text, &stderr_text, &exit_status, &error);
636 if (!result || exit_status != 0)
637 g_warning ("Failed to get languages, locale -a returned %d: %s", exit_status, error->message);
643 tokens = g_strsplit_set (stdout_text, "\n\r", -1);
644 for (i = 0; tokens[i]; i++)
646 LdmLanguage *language;
649 code = g_strchug (tokens[i]);
653 /* Ignore the non-interesting languages */
654 if (strcmp (code, "C") == 0 || strcmp (code, "POSIX") == 0)
657 language = ldm_language_new (code);
658 greeter->priv->languages = g_list_append (greeter->priv->languages, language);
664 g_clear_error (&error);
665 g_free (stdout_text);
666 g_free (stderr_text);
668 greeter->priv->have_languages = TRUE;
672 * ldm_greeter_get_default_language:
673 * @greeter: A #LdmGreeter
675 * Get the default language.
677 * Return value: The default language.
680 ldm_greeter_get_default_language (LdmGreeter *greeter)
682 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
683 return getenv ("LANG");
687 * ldm_greeter_get_languages:
688 * @greeter: A #LdmGreeter
690 * Get a list of languages to present to the user.
692 * Return value: (element-type LdmLanguage): A list of #LdmLanguage that should be presented to the user.
695 ldm_greeter_get_languages (LdmGreeter *greeter)
697 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
698 update_languages (greeter);
699 return greeter->priv->languages;
703 ldm_greeter_get_default_layout (LdmGreeter *greeter)
705 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
706 return greeter->priv->default_layout;
710 layout_cb (XklConfigRegistry *config,
711 const XklConfigItem *item,
714 LdmGreeter *greeter = data;
717 layout = ldm_layout_new (item->name, item->short_description, item->description);
718 greeter->priv->layouts = g_list_append (greeter->priv->layouts, layout);
722 setup_display (LdmGreeter *greeter)
724 if (!greeter->priv->display)
725 greeter->priv->display = XOpenDisplay (NULL);
729 setup_xkl (LdmGreeter *greeter)
731 setup_display (greeter);
732 greeter->priv->xkl_engine = xkl_engine_get_instance (greeter->priv->display);
733 greeter->priv->xkl_config = xkl_config_rec_new ();
734 if (!xkl_config_rec_get_from_server (greeter->priv->xkl_config, greeter->priv->xkl_engine))
735 g_warning ("Failed to get Xkl configuration from server");
736 greeter->priv->layout = g_strdup (greeter->priv->xkl_config->layouts[0]);
740 * ldm_greeter_get_layouts:
741 * @greeter: A #LdmGreeter
743 * Get a list of keyboard layouts to present to the user.
745 * Return value: (element-type LdmLayout): A list of #LdmLayout that should be presented to the user.
748 ldm_greeter_get_layouts (LdmGreeter *greeter)
750 XklConfigRegistry *registry;
752 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
754 if (greeter->priv->have_layouts)
755 return greeter->priv->layouts;
759 registry = xkl_config_registry_get_instance (greeter->priv->xkl_engine);
760 xkl_config_registry_load (registry, FALSE);
761 xkl_config_registry_foreach_layout (registry, layout_cb, greeter);
762 g_object_unref (registry);
763 greeter->priv->have_layouts = TRUE;
765 return greeter->priv->layouts;
769 * ldm_greeter_set_layout:
770 * @greeter: A #LdmGreeter
771 * @layout: The layout to use
773 * Set the layout for this session.
776 ldm_greeter_set_layout (LdmGreeter *greeter, const gchar *layout)
778 XklConfigRec *config;
780 g_return_if_fail (LDM_IS_GREETER (greeter));
781 g_return_if_fail (layout != NULL);
783 g_debug ("Setting keyboard layout to %s", layout);
787 config = xkl_config_rec_new ();
788 config->layouts = g_malloc (sizeof (gchar *) * 2);
789 config->model = g_strdup (greeter->priv->xkl_config->model);
790 config->layouts[0] = g_strdup (layout);
791 config->layouts[1] = NULL;
792 if (!xkl_config_rec_activate (config, greeter->priv->xkl_engine))
793 g_warning ("Failed to activate XKL config");
795 greeter->priv->layout = g_strdup (layout);
796 g_object_unref (config);
800 * ldm_greeter_get_layout:
801 * @greeter: A #LdmGreeter
803 * Get the current keyboard layout.
805 * Return value: The currently active layout for this user.
808 ldm_greeter_get_layout (LdmGreeter *greeter)
810 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
812 return greeter->priv->layout;
816 update_sessions (LdmGreeter *greeter)
819 GError *error = NULL;
821 if (greeter->priv->have_sessions)
824 directory = g_dir_open (XSESSIONS_DIR, 0, &error);
826 g_warning ("Failed to open sessions directory: %s", error->message);
827 g_clear_error (&error);
833 const gchar *filename;
838 filename = g_dir_read_name (directory);
839 if (filename == NULL)
842 if (!g_str_has_suffix (filename, ".desktop"))
845 key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
846 path = g_build_filename (XSESSIONS_DIR, filename, NULL);
847 g_debug ("Loading session %s", path);
849 key_file = g_key_file_new ();
850 result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
852 g_warning ("Failed to load session file %s: %s:", path, error->message);
853 g_clear_error (&error);
855 if (result && !g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL))
857 gchar *domain, *name, *comment;
859 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
860 domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
862 domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
864 name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
865 comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
867 comment = g_strdup ("");
870 g_debug ("Loaded session %s (%s, %s)", key, name, comment);
871 greeter->priv->sessions = g_list_append (greeter->priv->sessions, ldm_session_new (key, name, comment));
874 g_warning ("Invalid session %s: %s", path, error->message);
875 g_clear_error (&error);
883 g_key_file_free (key_file);
886 g_dir_close (directory);
888 greeter->priv->have_sessions = TRUE;
892 * ldm_greeter_get_sessions:
893 * @greeter: A #LdmGreeter
895 * Get the available sessions.
897 * Return value: (element-type LdmSession): A list of #LdmSession
900 ldm_greeter_get_sessions (LdmGreeter *greeter)
902 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
903 update_sessions (greeter);
904 return greeter->priv->sessions;
908 * ldm_greeter_get_default_session:
909 * @greeter: A #LdmGreeter
911 * Get the default session to use.
913 * Return value: The session name
916 ldm_greeter_get_default_session (LdmGreeter *greeter)
918 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
919 return greeter->priv->default_session;
923 * ldm_greeter_get_timed_login_user:
924 * @greeter: A #LdmGreeter
926 * Get the user to log in by as default.
928 * Return value: A username
931 ldm_greeter_get_timed_login_user (LdmGreeter *greeter)
933 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
934 return greeter->priv->timed_user;
938 * ldm_greeter_get_timed_login_delay:
939 * @greeter: A #LdmGreeter
941 * Get the number of seconds to wait until logging in as the default user.
943 * Return value: The number of seconds before logging in as the default user
946 ldm_greeter_get_timed_login_delay (LdmGreeter *greeter)
948 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
949 return greeter->priv->login_delay;
953 * ldm_greeter_cancel_timed_login:
954 * @greeter: A #LdmGreeter
956 * Cancel the login as the default user.
959 ldm_greeter_cancel_timed_login (LdmGreeter *greeter)
961 g_return_if_fail (LDM_IS_GREETER (greeter));
963 if (greeter->priv->login_timeout)
964 g_source_remove (greeter->priv->login_timeout);
965 greeter->priv->login_timeout = 0;
969 * ldm_greeter_start_authentication:
970 * @greeter: A #LdmGreeter
971 * @username: A username
973 * Starts the authentication procedure for a user.
976 ldm_greeter_start_authentication (LdmGreeter *greeter, const char *username)
978 g_return_if_fail (LDM_IS_GREETER (greeter));
979 g_return_if_fail (username != NULL);
981 greeter->priv->is_authenticated = FALSE;
982 g_free (greeter->priv->authentication_user);
983 greeter->priv->authentication_user = g_strdup (username);
984 g_debug ("Starting authentication for user %s...", username);
985 write_header (greeter, GREETER_MESSAGE_START_AUTHENTICATION, string_length (username));
986 write_string (greeter, username);
991 * ldm_greeter_provide_secret:
992 * @greeter: A #LdmGreeter
993 * @secret: Response to a prompt
995 * Provide secret information from a prompt.
998 ldm_greeter_provide_secret (LdmGreeter *greeter, const gchar *secret)
1000 g_return_if_fail (LDM_IS_GREETER (greeter));
1001 g_return_if_fail (secret != NULL);
1003 g_debug ("Providing secret to display manager");
1004 write_header (greeter, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, int_length () + string_length (secret));
1005 // FIXME: Could be multiple secrets required
1006 write_int (greeter, 1);
1007 write_string (greeter, secret);
1012 * ldm_greeter_cancel_authentication:
1013 * @greeter: A #LdmGreeter
1015 * Cancel the current user authentication.
1018 ldm_greeter_cancel_authentication (LdmGreeter *greeter)
1020 g_return_if_fail (LDM_IS_GREETER (greeter));
1024 * ldm_greeter_get_in_authentication:
1025 * @greeter: A #LdmGreeter
1027 * Checks if the greeter is in the process of authenticating.
1029 * Return value: TRUE if the greeter is authenticating a user.
1032 ldm_greeter_get_in_authentication (LdmGreeter *greeter)
1034 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1035 return greeter->priv->in_authentication;
1039 * ldm_greeter_get_is_authenticated:
1040 * @greeter: A #LdmGreeter
1042 * Checks if the greeter has successfully authenticated.
1044 * Return value: TRUE if the greeter is authenticated for login.
1047 ldm_greeter_get_is_authenticated (LdmGreeter *greeter)
1049 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1050 return greeter->priv->is_authenticated;
1054 * ldm_greeter_get_authentication_user:
1055 * @greeter: A #LdmGreeter
1057 * Get the user that is being authenticated.
1059 * Return value: The username of the authentication user being authenticated or NULL if no authentication in progress.
1062 ldm_greeter_get_authentication_user (LdmGreeter *greeter)
1064 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1065 return greeter->priv->authentication_user;
1069 * ldm_greeter_login:
1070 * @greeter: A #LdmGreeter
1071 * @username: The user to log in as
1072 * @session: (allow-none): The session to log into or NULL to use the default
1073 * @language: (allow-none): The language to use or NULL to use the default
1075 * Login a user to a session.
1078 ldm_greeter_login (LdmGreeter *greeter, const gchar *username, const gchar *session, const gchar *language)
1080 g_return_if_fail (LDM_IS_GREETER (greeter));
1081 g_return_if_fail (username != NULL);
1088 g_debug ("Logging in");
1089 write_header (greeter, GREETER_MESSAGE_LOGIN, string_length (username) + string_length (session) + string_length (language));
1090 write_string (greeter, username);
1091 write_string (greeter, session);
1092 write_string (greeter, language);
1097 * ldm_greeter_login_with_defaults:
1098 * @greeter: A #LdmGreeter
1099 * @username: The user to log in as
1101 * Login a user to a session using default settings for that user.
1104 ldm_greeter_login_with_defaults (LdmGreeter *greeter, const gchar *username)
1106 g_return_if_fail (LDM_IS_GREETER (greeter));
1107 g_return_if_fail (username != NULL);
1108 ldm_greeter_login (greeter, username, NULL, NULL);
1112 upower_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1116 GError *error = NULL;
1117 gboolean function_result = FALSE;
1119 proxy = g_dbus_proxy_new_sync (greeter->priv->system_bus,
1120 G_DBUS_PROXY_FLAGS_NONE,
1122 "org.freedesktop.UPower",
1123 "/org/freedesktop/UPower",
1124 "org.freedesktop.UPower",
1126 result = g_dbus_proxy_call_sync (proxy,
1129 G_DBUS_CALL_FLAGS_NONE,
1133 g_object_unref (proxy);
1136 g_warning ("Error calling UPower function %s: %s", function, error->message);
1137 g_clear_error (&error);
1141 if (g_variant_is_of_type (result, G_VARIANT_TYPE_BOOLEAN))
1142 function_result = g_variant_get_boolean (result);
1144 g_variant_unref (result);
1145 return function_result;
1149 * ldm_greeter_get_can_suspend:
1150 * @greeter: A #LdmGreeter
1152 * Checks if the greeter is authorized to do a system suspend.
1154 * Return value: TRUE if the greeter can suspend the system
1157 ldm_greeter_get_can_suspend (LdmGreeter *greeter)
1159 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1160 return upower_call_function (greeter, "SuspendAllowed", TRUE);
1164 * ldm_greeter_suspend:
1165 * @greeter: A #LdmGreeter
1167 * Triggers a system suspend.
1170 ldm_greeter_suspend (LdmGreeter *greeter)
1172 g_return_if_fail (LDM_IS_GREETER (greeter));
1173 upower_call_function (greeter, "Suspend", FALSE);
1177 * ldm_greeter_get_can_hibernate:
1178 * @greeter: A #LdmGreeter
1180 * Checks if the greeter is authorized to do a system hibernate.
1182 * Return value: TRUE if the greeter can hibernate the system
1185 ldm_greeter_get_can_hibernate (LdmGreeter *greeter)
1187 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1188 return upower_call_function (greeter, "HibernateAllowed", TRUE);
1192 * ldm_greeter_hibernate:
1193 * @greeter: A #LdmGreeter
1195 * Triggers a system hibernate.
1198 ldm_greeter_hibernate (LdmGreeter *greeter)
1200 g_return_if_fail (LDM_IS_GREETER (greeter));
1201 upower_call_function (greeter, "Hibernate", FALSE);
1205 ck_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1209 GError *error = NULL;
1210 gboolean function_result = FALSE;
1212 proxy = g_dbus_proxy_new_sync (greeter->priv->system_bus,
1213 G_DBUS_PROXY_FLAGS_NONE,
1215 "org.freedesktop.ConsoleKit",
1216 "/org/freedesktop/ConsoleKit/Manager",
1217 "org.freedesktop.ConsoleKit.Manager",
1219 result = g_dbus_proxy_call_sync (proxy,
1222 G_DBUS_CALL_FLAGS_NONE,
1226 g_object_unref (proxy);
1229 g_warning ("Error calling ConsoleKit function %s: %s", function, error->message);
1230 g_clear_error (&error);
1234 if (g_variant_is_of_type (result, G_VARIANT_TYPE_BOOLEAN))
1235 function_result = g_variant_get_boolean (result);
1237 g_variant_unref (result);
1238 return function_result;
1242 * ldm_greeter_get_can_restart:
1243 * @greeter: A #LdmGreeter
1245 * Checks if the greeter is authorized to do a system restart.
1247 * Return value: TRUE if the greeter can restart the system
1250 ldm_greeter_get_can_restart (LdmGreeter *greeter)
1252 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1253 return ck_call_function (greeter, "CanRestart", TRUE);
1257 * ldm_greeter_restart:
1258 * @greeter: A #LdmGreeter
1260 * Triggers a system restart.
1263 ldm_greeter_restart (LdmGreeter *greeter)
1265 g_return_if_fail (LDM_IS_GREETER (greeter));
1266 ck_call_function (greeter, "Restart", FALSE);
1270 * ldm_greeter_get_can_shutdown:
1271 * @greeter: A #LdmGreeter
1273 * Checks if the greeter is authorized to do a system shutdown.
1275 * Return value: TRUE if the greeter can shutdown the system
1278 ldm_greeter_get_can_shutdown (LdmGreeter *greeter)
1280 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1281 return ck_call_function (greeter, "CanStop", TRUE);
1285 * ldm_greeter_shutdown:
1286 * @greeter: A #LdmGreeter
1288 * Triggers a system shutdown.
1291 ldm_greeter_shutdown (LdmGreeter *greeter)
1293 g_return_if_fail (LDM_IS_GREETER (greeter));
1294 ck_call_function (greeter, "Stop", FALSE);
1298 * ldm_greeter_get_user_defaults:
1299 * @greeter: A #LdmGreeter
1300 * @username: The user to check
1301 * @language: (out): Default language for this user.
1302 * @layout: (out): Default keyboard layout for this user.
1303 * @session: (out): Default session for this user.
1305 * Get the default settings for a given user.
1308 ldm_greeter_get_user_defaults (LdmGreeter *greeter, const gchar *username, gchar **language, gchar **layout, gchar **session)
1310 GError *error = NULL;
1312 gboolean got_defaults = FALSE;
1314 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1315 g_return_val_if_fail (username != NULL, FALSE);
1317 result = g_dbus_proxy_call_sync (greeter->priv->user_proxy,
1319 g_variant_new ("(s)", username),
1320 G_DBUS_CALL_FLAGS_NONE,
1326 g_warning ("Failed to get user defaults: %s", error->message);
1327 g_clear_error (&error);
1332 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(sss)")))
1334 g_variant_get (result, "(sss)", language, layout, session);
1335 got_defaults = TRUE;
1338 g_variant_unref (result);
1340 return got_defaults;
1344 ldm_greeter_init (LdmGreeter *greeter)
1346 greeter->priv = G_TYPE_INSTANCE_GET_PRIVATE (greeter, LDM_TYPE_GREETER, LdmGreeterPrivate);
1347 greeter->priv->read_buffer = g_malloc (HEADER_SIZE);
1349 g_debug ("default-language=%s", ldm_greeter_get_default_language (greeter));
1353 ldm_greeter_set_property (GObject *object,
1355 const GValue *value,
1360 self = LDM_GREETER (object);
1364 ldm_greeter_set_layout(self, g_value_get_string (value));
1367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1373 ldm_greeter_get_property (GObject *object,
1380 self = LDM_GREETER (object);
1384 g_value_set_string (value, ldm_greeter_get_hostname (self));
1386 case PROP_NUM_USERS:
1387 g_value_set_int (value, ldm_greeter_get_num_users (self));
1391 case PROP_DEFAULT_LANGUAGE:
1392 g_value_set_string (value, ldm_greeter_get_default_language (self));
1397 g_value_set_string (value, ldm_greeter_get_layout (self));
1401 case PROP_DEFAULT_SESSION:
1402 g_value_set_string (value, ldm_greeter_get_default_session (self));
1404 case PROP_TIMED_LOGIN_USER:
1405 g_value_set_string (value, ldm_greeter_get_timed_login_user (self));
1407 case PROP_TIMED_LOGIN_DELAY:
1408 g_value_set_int (value, ldm_greeter_get_timed_login_delay (self));
1410 case PROP_AUTHENTICATION_USER:
1411 g_value_set_string (value, ldm_greeter_get_authentication_user (self));
1413 case PROP_IN_AUTHENTICATION:
1414 g_value_set_boolean (value, ldm_greeter_get_in_authentication (self));
1416 case PROP_IS_AUTHENTICATED:
1417 g_value_set_boolean (value, ldm_greeter_get_is_authenticated (self));
1419 case PROP_CAN_SUSPEND:
1420 g_value_set_boolean (value, ldm_greeter_get_can_suspend (self));
1422 case PROP_CAN_HIBERNATE:
1423 g_value_set_boolean (value, ldm_greeter_get_can_hibernate (self));
1425 case PROP_CAN_RESTART:
1426 g_value_set_boolean (value, ldm_greeter_get_can_restart (self));
1428 case PROP_CAN_SHUTDOWN:
1429 g_value_set_boolean (value, ldm_greeter_get_can_shutdown (self));
1432 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1438 ldm_greeter_class_init (LdmGreeterClass *klass)
1440 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1442 g_type_class_add_private (klass, sizeof (LdmGreeterPrivate));
1444 object_class->set_property = ldm_greeter_set_property;
1445 object_class->get_property = ldm_greeter_get_property;
1447 g_object_class_install_property (object_class,
1449 g_param_spec_string ("hostname",
1451 "Hostname displaying greeter for",
1454 g_object_class_install_property (object_class,
1456 g_param_spec_int ("num-users",
1458 "Number of login users",
1461 /*g_object_class_install_property (object_class,
1463 g_param_spec_list ("users",
1465 "Users that can login"));
1466 g_object_class_install_property (object_class,
1467 PROP_DEFAULT_LANGUAGE,
1468 g_param_spec_string ("default-language",
1472 G_PARAM_READWRITE));
1473 g_object_class_install_property (object_class,
1475 g_param_spec_list ("layouts",
1477 "Available keyboard layouts"));*/
1478 g_object_class_install_property (object_class,
1480 g_param_spec_string ("layout",
1482 "Current keyboard layout",
1484 G_PARAM_READWRITE));
1485 /*g_object_class_install_property (object_class,
1487 g_param_spec_list ("sessions",
1489 "Available sessions"));*/
1490 g_object_class_install_property (object_class,
1491 PROP_DEFAULT_SESSION,
1492 g_param_spec_string ("default-session",
1496 G_PARAM_READWRITE));
1497 g_object_class_install_property (object_class,
1498 PROP_TIMED_LOGIN_USER,
1499 g_param_spec_string ("timed-login-user",
1501 "User to login as when timed expires",
1504 g_object_class_install_property (object_class,
1505 PROP_TIMED_LOGIN_DELAY,
1506 g_param_spec_int ("login-delay",
1508 "Number of seconds until logging in as default user",
1509 G_MININT, G_MAXINT, 0,
1511 g_object_class_install_property (object_class,
1512 PROP_AUTHENTICATION_USER,
1513 g_param_spec_string ("authentication-user",
1514 "authentication-user",
1515 "The user being authenticated",
1518 g_object_class_install_property (object_class,
1519 PROP_IN_AUTHENTICATION,
1520 g_param_spec_boolean ("in-authentication",
1521 "in-authentication",
1522 "TRUE if a user is being authenticated",
1525 g_object_class_install_property (object_class,
1526 PROP_IS_AUTHENTICATED,
1527 g_param_spec_boolean ("is-authenticated",
1529 "TRUE if the selected user is authenticated",
1532 g_object_class_install_property (object_class,
1534 g_param_spec_boolean ("can-suspend",
1536 "TRUE if allowed to suspend the system",
1539 g_object_class_install_property (object_class,
1541 g_param_spec_boolean ("can-hibernate",
1543 "TRUE if allowed to hibernate the system",
1546 g_object_class_install_property (object_class,
1548 g_param_spec_boolean ("can-restart",
1550 "TRUE if allowed to restart the system",
1553 g_object_class_install_property (object_class,
1555 g_param_spec_boolean ("can-shutdown",
1557 "TRUE if allowed to shutdown the system",
1562 * LdmGreeter::connected:
1563 * @greeter: A #LdmGreeter
1565 * The ::connected signal gets emitted when the greeter connects to the
1568 signals[CONNECTED] =
1569 g_signal_new ("connected",
1570 G_TYPE_FROM_CLASS (klass),
1572 G_STRUCT_OFFSET (LdmGreeterClass, connected),
1574 g_cclosure_marshal_VOID__VOID,
1578 * LdmGreeter::show-prompt:
1579 * @greeter: A #LdmGreeter
1580 * @text: Prompt text
1582 * The ::show-prompt signal gets emitted when the greeter should show a
1583 * prompt to the user. The given text should be displayed and an input
1584 * field for the user to provide a response.
1586 * Call ldm_greeter_provide_secret() with the resultant input or
1587 * ldm_greeter_cancel_authentication() to abort the authentication.
1589 signals[SHOW_PROMPT] =
1590 g_signal_new ("show-prompt",
1591 G_TYPE_FROM_CLASS (klass),
1593 G_STRUCT_OFFSET (LdmGreeterClass, show_prompt),
1595 g_cclosure_marshal_VOID__STRING,
1596 G_TYPE_NONE, 1, G_TYPE_STRING);
1599 * LdmGreeter::show-message:
1600 * @greeter: A #LdmGreeter
1601 * @text: Message text
1603 * The ::show-message signal gets emitted when the greeter
1604 * should show an informational message to the user.
1606 signals[SHOW_MESSAGE] =
1607 g_signal_new ("show-message",
1608 G_TYPE_FROM_CLASS (klass),
1610 G_STRUCT_OFFSET (LdmGreeterClass, show_message),
1612 g_cclosure_marshal_VOID__STRING,
1613 G_TYPE_NONE, 1, G_TYPE_STRING);
1616 * LdmGreeter::show-error:
1617 * @greeter: A #LdmGreeter
1618 * @text: Message text
1620 * The ::show-error signal gets emitted when the greeter
1621 * should show an error message to the user.
1623 signals[SHOW_ERROR] =
1624 g_signal_new ("show-error",
1625 G_TYPE_FROM_CLASS (klass),
1627 G_STRUCT_OFFSET (LdmGreeterClass, show_error),
1629 g_cclosure_marshal_VOID__STRING,
1630 G_TYPE_NONE, 1, G_TYPE_STRING);
1633 * LdmGreeter::authentication-complete:
1634 * @greeter: A #LdmGreeter
1636 * The ::authentication-complete signal gets emitted when the greeter
1637 * has completed authentication.
1639 * Call ldm_greeter_get_is_authenticated() to check if the authentication
1642 signals[AUTHENTICATION_COMPLETE] =
1643 g_signal_new ("authentication-complete",
1644 G_TYPE_FROM_CLASS (klass),
1646 G_STRUCT_OFFSET (LdmGreeterClass, authentication_complete),
1648 g_cclosure_marshal_VOID__VOID,
1652 * LdmGreeter::timed-login:
1653 * @greeter: A #LdmGreeter
1654 * @username: A username
1656 * The ::timed-login signal gets emitted when the default user timer
1659 signals[TIMED_LOGIN] =
1660 g_signal_new ("timed-login",
1661 G_TYPE_FROM_CLASS (klass),
1663 G_STRUCT_OFFSET (LdmGreeterClass, timed_login),
1665 g_cclosure_marshal_VOID__STRING,
1666 G_TYPE_NONE, 1, G_TYPE_STRING);
1670 * @greeter: A #LdmGreeter
1672 * The ::quit signal gets emitted when the greeter should exit.
1675 g_signal_new ("quit",
1676 G_TYPE_FROM_CLASS (klass),
1678 G_STRUCT_OFFSET (LdmGreeterClass, quit),
1680 g_cclosure_marshal_VOID__VOID,