diff options
author | Robert Ancell <robert.ancell@canonical.com> | 2015-08-05 15:32:06 +1200 |
---|---|---|
committer | Robert Ancell <robert.ancell@canonical.com> | 2015-08-05 15:32:06 +1200 |
commit | 8e5f15c3917230d95c1d58a69a526ce2de1228b2 (patch) | |
tree | 1d8071dfcf5cf089b3670f20ae9d36f62618a3b1 /src | |
parent | 51d955565e4731f85be23fb5203cb2ceac8099bc (diff) | |
parent | 645e6a0d231f2b3616ee8330b342d3efbf2c5264 (diff) | |
download | lightdm-8e5f15c3917230d95c1d58a69a526ce2de1228b2.tar.gz |
Merge with trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/greeter.c | 27 | ||||
-rw-r--r-- | src/lightdm.c | 173 | ||||
-rw-r--r-- | src/login1.c | 17 | ||||
-rw-r--r-- | src/login1.h | 2 | ||||
-rw-r--r-- | src/seat-unity.c | 8 | ||||
-rw-r--r-- | src/seat-xremote.c | 2 | ||||
-rw-r--r-- | src/seat.c | 56 | ||||
-rw-r--r-- | src/seat.h | 6 | ||||
-rw-r--r-- | src/session-child.c | 10 | ||||
-rw-r--r-- | src/session.c | 11 | ||||
-rw-r--r-- | src/session.h | 2 | ||||
-rw-r--r-- | src/unity-system-compositor.c | 3 | ||||
-rw-r--r-- | src/xdmcp-protocol.c | 28 | ||||
-rw-r--r-- | src/xdmcp-server.c | 139 |
14 files changed, 348 insertions, 136 deletions
diff --git a/src/greeter.c b/src/greeter.c index e1d47f86..b9f4f55a 100644 --- a/src/greeter.c +++ b/src/greeter.c @@ -76,6 +76,8 @@ struct GreeterPrivate gboolean guest_account_authenticated; /* Communication channels to communicate with */ + int to_greeter_input; + int from_greeter_output; GIOChannel *to_greeter_channel; GIOChannel *from_greeter_channel; guint from_greeter_watch; @@ -954,6 +956,7 @@ greeter_start (Session *session) { Greeter *greeter = GREETER (session); int to_greeter_pipe[2], from_greeter_pipe[2]; + int to_greeter_output, from_greeter_input; gboolean result = FALSE; gchar *value; GError *error = NULL; @@ -964,12 +967,16 @@ greeter_start (Session *session) g_warning ("Failed to create pipes: %s", strerror (errno)); return FALSE; } - greeter->priv->to_greeter_channel = g_io_channel_unix_new (to_greeter_pipe[1]); + to_greeter_output = to_greeter_pipe[0]; + greeter->priv->to_greeter_input = to_greeter_pipe[1]; + greeter->priv->to_greeter_channel = g_io_channel_unix_new (greeter->priv->to_greeter_input); g_io_channel_set_encoding (greeter->priv->to_greeter_channel, NULL, &error); if (error) g_warning ("Failed to set encoding on to greeter channel to binary: %s\n", error->message); g_clear_error (&error); - greeter->priv->from_greeter_channel = g_io_channel_unix_new (from_greeter_pipe[0]); + greeter->priv->from_greeter_output = from_greeter_pipe[0]; + from_greeter_input = from_greeter_pipe[1]; + greeter->priv->from_greeter_channel = g_io_channel_unix_new (greeter->priv->from_greeter_output); g_io_channel_set_encoding (greeter->priv->from_greeter_channel, NULL, &error); if (error) g_warning ("Failed to set encoding on from greeter channel to binary: %s\n", error->message); @@ -978,22 +985,22 @@ greeter_start (Session *session) greeter->priv->from_greeter_watch = g_io_add_watch (greeter->priv->from_greeter_channel, G_IO_IN | G_IO_HUP, read_cb, greeter); /* Let the greeter session know how to communicate with the daemon */ - value = g_strdup_printf ("%d", from_greeter_pipe[1]); + value = g_strdup_printf ("%d", from_greeter_input); session_set_env (SESSION (greeter), "LIGHTDM_TO_SERVER_FD", value); g_free (value); - value = g_strdup_printf ("%d", to_greeter_pipe[0]); + value = g_strdup_printf ("%d", to_greeter_output); session_set_env (SESSION (greeter), "LIGHTDM_FROM_SERVER_FD", value); g_free (value); /* Don't allow the daemon end of the pipes to be accessed in child processes */ - fcntl (to_greeter_pipe[1], F_SETFD, FD_CLOEXEC); - fcntl (from_greeter_pipe[0], F_SETFD, FD_CLOEXEC); + fcntl (greeter->priv->to_greeter_input, F_SETFD, FD_CLOEXEC); + fcntl (greeter->priv->from_greeter_output, F_SETFD, FD_CLOEXEC); result = SESSION_CLASS (greeter_parent_class)->start (session); /* Close the session ends of the pipe */ - close (to_greeter_pipe[0]); - close (from_greeter_pipe[1]); + close (to_greeter_output); + close (from_greeter_input); return result; } @@ -1029,6 +1036,8 @@ greeter_init (Greeter *greeter) greeter->priv->read_buffer = secure_malloc (greeter, HEADER_SIZE); greeter->priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); greeter->priv->use_secure_memory = config_get_boolean (config_get_instance (), "LightDM", "lock-memory"); + greeter->priv->to_greeter_input = -1; + greeter->priv->from_greeter_output = -1; } static void @@ -1049,6 +1058,8 @@ greeter_finalize (GObject *object) g_signal_handlers_disconnect_matched (self->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); g_object_unref (self->priv->authentication_session); } + close (self->priv->to_greeter_input); + close (self->priv->from_greeter_output); if (self->priv->to_greeter_channel) g_io_channel_unref (self->priv->to_greeter_channel); if (self->priv->from_greeter_channel) diff --git a/src/lightdm.c b/src/lightdm.c index f87df156..72f7eb0c 100644 --- a/src/lightdm.c +++ b/src/lightdm.c @@ -153,18 +153,16 @@ get_config_sections (const gchar *seat_name) gchar **groups, **i; GList *config_sections = NULL; - config_sections = g_list_append (config_sections, g_strdup ("SeatDefaults")); - - if (!seat_name) - return config_sections; + /* Load seat defaults first */ + config_sections = g_list_append (config_sections, g_strdup ("Seat:*")); groups = config_get_groups (config_get_instance ()); for (i = groups; *i; i++) { - if (g_str_has_prefix (*i, "Seat:")) + if (g_str_has_prefix (*i, "Seat:") && strcmp (*i, "Seat:*") != 0) { const gchar *seat_name_glob = *i + strlen ("Seat:"); - if (g_pattern_match_simple (seat_name_glob, seat_name)) + if (g_pattern_match_simple (seat_name_glob, seat_name ? seat_name : "")) config_sections = g_list_append (config_sections, g_strdup (*i)); } } @@ -184,8 +182,9 @@ set_seat_properties (Seat *seat, const gchar *seat_name) for (link = sections; link; link = link->next) { const gchar *section = link->data; - g_debug ("Loading properties from config section %s", section); keys = config_get_keys (config_get_instance (), section); + + l_debug (seat, "Loading properties from config section %s", section); for (i = 0; keys && keys[i]; i++) { gchar *value = config_get_string (config_get_instance (), section, keys[i]); @@ -611,11 +610,6 @@ seat_bus_entry_free (gpointer data) { SeatBusEntry *entry = data; - g_dbus_connection_unregister_object (bus, entry->bus_id); - - emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Seats", get_seat_list ()); - emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SeatRemoved", entry->path); - g_free (entry->path); g_free (entry); } @@ -625,14 +619,6 @@ session_bus_entry_free (gpointer data) { SessionBusEntry *entry = data; - g_dbus_connection_unregister_object (bus, entry->bus_id); - - emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Sessions", get_session_list (NULL)); - emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SessionRemoved", entry->path); - - emit_object_value_changed (bus, entry->seat_path, "org.freedesktop.DisplayManager.Seat", "Sessions", get_session_list (entry->seat_path)); - emit_object_signal (bus, entry->seat_path, "SessionRemoved", entry->path); - g_free (entry->path); g_free (entry->seat_path); g_free (entry); @@ -659,7 +645,6 @@ running_user_session_cb (Seat *seat, Session *session) session_set_env (session, "XDG_SESSION_PATH", path); g_object_set_data_full (G_OBJECT (session), "XDG_SESSION_PATH", path, g_free); - seat_entry = g_hash_table_lookup (seat_bus_entries, seat); session_entry = session_bus_entry_new (g_object_get_data (G_OBJECT (session), "XDG_SESSION_PATH"), seat_entry ? seat_entry->path : NULL); g_hash_table_insert (session_bus_entries, g_object_ref (session), session_entry); @@ -685,8 +670,28 @@ running_user_session_cb (Seat *seat, Session *session) static void session_removed_cb (Seat *seat, Session *session) { + SessionBusEntry *entry; + gchar *seat_path = NULL; + g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat); + + entry = g_hash_table_lookup (session_bus_entries, session); + if (entry) + { + g_dbus_connection_unregister_object (bus, entry->bus_id); + emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SessionRemoved", entry->path); + emit_object_signal (bus, entry->seat_path, "SessionRemoved", entry->path); + seat_path = g_strdup (entry->seat_path); + } + g_hash_table_remove (session_bus_entries, session); + + if (seat_path) + { + emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Sessions", get_session_list (NULL)); + emit_object_value_changed (bus, seat_path, "org.freedesktop.DisplayManager.Seat", "Sessions", get_session_list (seat_path)); + g_free (seat_path); + } } static void @@ -730,7 +735,18 @@ seat_added_cb (DisplayManager *display_manager, Seat *seat) static void seat_removed_cb (DisplayManager *display_manager, Seat *seat) { + SeatBusEntry *entry; + + entry = g_hash_table_lookup (seat_bus_entries, seat); + if (entry) + { + g_dbus_connection_unregister_object (bus, entry->bus_id); + emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SeatRemoved", entry->path); + } + g_hash_table_remove (seat_bus_entries, seat); + + emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Seats", get_seat_list ()); } static gboolean @@ -1068,6 +1084,48 @@ login1_can_graphical_changed_cb (Login1Seat *login1_seat) } static void +login1_active_session_changed_cb (Login1Seat *login1_seat, const gchar *login1_session_id) +{ + g_debug ("Seat %s changes active session to %s", login1_seat_get_id (login1_seat), login1_session_id); + + Seat *seat; + seat = display_manager_get_seat (display_manager, login1_seat_get_id (login1_seat)); + + if (seat) + { + Session *active_session; + active_session = seat_get_expected_active_session (seat); + + if (g_strcmp0 (login1_session_id, session_get_login1_session_id (active_session)) == 0) + { + // Session is already active + g_debug ("Session %s is already active", login1_session_id); + return; + } + + active_session = seat_find_session_by_login1_id (seat, login1_session_id); + if (active_session != NULL) + { + g_debug ("Activating session %s", login1_session_id); + seat_set_externally_activated_session (seat, active_session); + return; + + } + } +} + +static gboolean +login1_add_seat (Login1Seat *login1_seat) +{ + if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical")) + g_signal_connect (login1_seat, "can-graphical-changed", G_CALLBACK (login1_can_graphical_changed_cb), NULL); + + g_signal_connect (login1_seat, LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED, G_CALLBACK (login1_active_session_changed_cb), NULL); + + return update_login1_seat (login1_seat); +} + +static void login1_service_seat_added_cb (Login1Service *service, Login1Seat *login1_seat) { if (login1_seat_get_can_graphical (login1_seat)) @@ -1075,9 +1133,7 @@ login1_service_seat_added_cb (Login1Service *service, Login1Seat *login1_seat) else g_debug ("Seat %s added from logind without graphical output", login1_seat_get_id (login1_seat)); - if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical")) - g_signal_connect (login1_seat, LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED, G_CALLBACK (login1_can_graphical_changed_cb), NULL); - update_login1_seat (login1_seat); + login1_add_seat (login1_seat); } static void @@ -1085,6 +1141,7 @@ login1_service_seat_removed_cb (Login1Service *service, Login1Seat *login1_seat) { g_debug ("Seat %s removed from logind", login1_seat_get_id (login1_seat)); g_signal_handlers_disconnect_matched (login1_seat, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, login1_can_graphical_changed_cb, NULL); + g_signal_handlers_disconnect_matched (login1_seat, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, login1_active_session_changed_cb, NULL); remove_login1_seat (login1_seat); } @@ -1319,36 +1376,38 @@ main (int argc, char **argv) config_set_string (config_get_instance (), "LightDM", "greeter-user", GREETER_USER); if (!config_has_key (config_get_instance (), "LightDM", "lock-memory")) config_set_boolean (config_get_instance (), "LightDM", "lock-memory", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "type")) - config_set_string (config_get_instance (), "SeatDefaults", "type", "xlocal"); - if (!config_has_key (config_get_instance (), "SeatDefaults", "pam-service")) - config_set_string (config_get_instance (), "SeatDefaults", "pam-service", "lightdm"); - if (!config_has_key (config_get_instance (), "SeatDefaults", "pam-autologin-service")) - config_set_string (config_get_instance (), "SeatDefaults", "pam-autologin-service", "lightdm-autologin"); - if (!config_has_key (config_get_instance (), "SeatDefaults", "pam-greeter-service")) - config_set_string (config_get_instance (), "SeatDefaults", "pam-greeter-service", "lightdm-greeter"); - if (!config_has_key (config_get_instance (), "SeatDefaults", "xserver-command")) - config_set_string (config_get_instance (), "SeatDefaults", "xserver-command", "X"); - if (!config_has_key (config_get_instance (), "SeatDefaults", "xserver-share")) - config_set_boolean (config_get_instance (), "SeatDefaults", "xserver-share", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "unity-compositor-command")) - config_set_string (config_get_instance (), "SeatDefaults", "unity-compositor-command", "unity-system-compositor"); - if (!config_has_key (config_get_instance (), "SeatDefaults", "start-session")) - config_set_boolean (config_get_instance (), "SeatDefaults", "start-session", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "allow-user-switching")) - config_set_boolean (config_get_instance (), "SeatDefaults", "allow-user-switching", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "allow-guest")) - config_set_boolean (config_get_instance (), "SeatDefaults", "allow-guest", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-allow-guest")) - config_set_boolean (config_get_instance (), "SeatDefaults", "greeter-allow-guest", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-show-remote-login")) - config_set_boolean (config_get_instance (), "SeatDefaults", "greeter-show-remote-login", TRUE); - if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-session")) - config_set_string (config_get_instance (), "SeatDefaults", "greeter-session", GREETER_SESSION); - if (!config_has_key (config_get_instance (), "SeatDefaults", "user-session")) - config_set_string (config_get_instance (), "SeatDefaults", "user-session", USER_SESSION); - if (!config_has_key (config_get_instance (), "SeatDefaults", "session-wrapper")) - config_set_string (config_get_instance (), "SeatDefaults", "session-wrapper", "lightdm-session"); + if (!config_has_key (config_get_instance (), "Seat:*", "type")) + config_set_string (config_get_instance (), "Seat:*", "type", "xlocal"); + if (!config_has_key (config_get_instance (), "Seat:*", "pam-service")) + config_set_string (config_get_instance (), "Seat:*", "pam-service", "lightdm"); + if (!config_has_key (config_get_instance (), "Seat:*", "pam-autologin-service")) + config_set_string (config_get_instance (), "Seat:*", "pam-autologin-service", "lightdm-autologin"); + if (!config_has_key (config_get_instance (), "Seat:*", "pam-greeter-service")) + config_set_string (config_get_instance (), "Seat:*", "pam-greeter-service", "lightdm-greeter"); + if (!config_has_key (config_get_instance (), "Seat:*", "xserver-command")) + config_set_string (config_get_instance (), "Seat:*", "xserver-command", "X"); + if (!config_has_key (config_get_instance (), "Seat:*", "xmir-command")) + config_set_string (config_get_instance (), "Seat:*", "xmir-command", "Xmir"); + if (!config_has_key (config_get_instance (), "Seat:*", "xserver-share")) + config_set_boolean (config_get_instance (), "Seat:*", "xserver-share", TRUE); + if (!config_has_key (config_get_instance (), "Seat:*", "unity-compositor-command")) + config_set_string (config_get_instance (), "Seat:*", "unity-compositor-command", "unity-system-compositor"); + if (!config_has_key (config_get_instance (), "Seat:*", "start-session")) + config_set_boolean (config_get_instance (), "Seat:*", "start-session", TRUE); + if (!config_has_key (config_get_instance (), "Seat:*", "allow-user-switching")) + config_set_boolean (config_get_instance (), "Seat:*", "allow-user-switching", TRUE); + if (!config_has_key (config_get_instance (), "Seat:*", "allow-guest")) + config_set_boolean (config_get_instance (), "Seat:*", "allow-guest", TRUE); + if (!config_has_key (config_get_instance (), "Seat:*", "greeter-allow-guest")) + config_set_boolean (config_get_instance (), "Seat:*", "greeter-allow-guest", TRUE); + if (!config_has_key (config_get_instance (), "Seat:*", "greeter-show-remote-login")) + config_set_boolean (config_get_instance (), "Seat:*", "greeter-show-remote-login", TRUE); + if (!config_has_key (config_get_instance (), "Seat:*", "greeter-session")) + config_set_string (config_get_instance (), "Seat:*", "greeter-session", GREETER_SESSION); + if (!config_has_key (config_get_instance (), "Seat:*", "user-session")) + config_set_string (config_get_instance (), "Seat:*", "user-session", USER_SESSION); + if (!config_has_key (config_get_instance (), "Seat:*", "session-wrapper")) + config_set_string (config_get_instance (), "Seat:*", "session-wrapper", "lightdm-session"); if (!config_has_key (config_get_instance (), "LightDM", "log-directory")) config_set_string (config_get_instance (), "LightDM", "log-directory", default_log_dir); g_free (default_log_dir); @@ -1432,9 +1491,7 @@ main (int argc, char **argv) for (link = login1_service_get_seats (login1_service_get_instance ()); link; link = link->next) { Login1Seat *login1_seat = link->data; - if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical")) - g_signal_connect (login1_seat, LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED, G_CALLBACK (login1_can_graphical_changed_cb), NULL); - if (!update_login1_seat (login1_seat)) + if (!login1_add_seat (login1_seat)) return EXIT_FAILURE; } } @@ -1449,7 +1506,7 @@ main (int argc, char **argv) g_debug ("Adding default seat"); - types = config_get_string_list (config_get_instance (), "SeatDefaults", "type"); + types = config_get_string_list (config_get_instance (), "Seat:*", "type"); for (type = types; type && *type; type++) { seat = seat_new (*type, "seat0"); diff --git a/src/login1.c b/src/login1.c index 83d64b6e..af8e8a8e 100644 --- a/src/login1.c +++ b/src/login1.c @@ -43,6 +43,7 @@ struct Login1ServicePrivate enum { CAN_GRAPHICAL_CHANGED, + ACTIVE_SESSION_CHANGED, LAST_SEAT_SIGNAL }; static guint seat_signals[LAST_SEAT_SIGNAL] = { 0 }; @@ -89,6 +90,12 @@ update_property (Login1Seat *seat, const gchar *name, GVariant *value) seat->priv->can_graphical = g_variant_get_boolean (value); g_signal_emit (seat, seat_signals[CAN_GRAPHICAL_CHANGED], 0); } + else if (strcmp (name, "ActiveSession") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE ("(so)"))) + { + const gchar *login1_session_id; + g_variant_get (value, "(&so)", &login1_session_id, NULL); + g_signal_emit (seat, seat_signals[ACTIVE_SESSION_CHANGED], 0, login1_session_id); + } } static void @@ -133,6 +140,7 @@ seat_properties_changed_cb (GDBusConnection *connection, { g_variant_get (result, "(v)", &value); update_property (seat, name, value); + g_variant_unref (value); g_variant_unref (result); } } @@ -531,4 +539,13 @@ login1_seat_class_init (Login1SeatClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); + + seat_signals[ACTIVE_SESSION_CHANGED] = + g_signal_new (LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED, + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (Login1SeatClass, active_session_changed), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, G_TYPE_STRING); } diff --git a/src/login1.h b/src/login1.h index c266e23d..e34e806b 100644 --- a/src/login1.h +++ b/src/login1.h @@ -26,6 +26,7 @@ G_BEGIN_DECLS #define LOGIN1_SERVICE_SIGNAL_SEAT_REMOVED "seat-removed" #define LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED "can-graphical-changed" +#define LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED "active-session-changed" typedef struct Login1SeatPrivate Login1SeatPrivate; @@ -39,6 +40,7 @@ typedef struct { GObjectClass parent_class; void (*can_graphical_changed)(Login1Seat *seat); + void (*active_session_changed)(Login1Seat *seat, const gchar *login1_session_id); } Login1SeatClass; typedef struct Login1ServicePrivate Login1ServicePrivate; diff --git a/src/seat-unity.c b/src/seat-unity.c index 32d30b23..642be0aa 100644 --- a/src/seat-unity.c +++ b/src/seat-unity.c @@ -203,9 +203,11 @@ create_x_server (Seat *seat) x_server = x_server_local_new (); - command = seat_get_string_property (seat, "xserver-command"); - if (command) - x_server_local_set_command (x_server, command); + command = seat_get_string_property (seat, "xmir-command"); + /* Fall back to using X if Xmir is not available as this was the previous way XMir worked */ + if (strcmp (command, "Xmir") == 0 && !g_find_program_in_path ("Xmir")) + command = seat_get_string_property (seat, "xserver-command"); + x_server_local_set_command (x_server, command); id = g_strdup_printf ("x-%d", SEAT_UNITY (seat)->priv->next_x_server_id); SEAT_UNITY (seat)->priv->next_x_server_id++; diff --git a/src/seat-xremote.c b/src/seat-xremote.c index 1a46f401..e860e9f3 100644 --- a/src/seat-xremote.c +++ b/src/seat-xremote.c @@ -41,7 +41,7 @@ seat_xremote_create_display_server (Seat *seat, Session *session) hostname = seat_get_string_property (seat, "xserver-hostname"); if (!hostname) - hostname = "localhost"; + hostname = "127.0.0.1"; number = seat_get_integer_property (seat, "xserver-display-number"); l_debug (seat, "Starting remote X display %s:%d", hostname, number); @@ -269,6 +269,54 @@ seat_get_next_session (Seat *seat) return seat->priv->next_session; } +/** + * Obtains the active session which lightdm expects to be active. + * + * This function is different from seat_get_active_session() in that the + * later (in the case of xlocal seats) dynamically finds the session that is + * really active (based on the active VT), whereas this function returns the + * session that lightdm activated last by itself, which may not be the actual + * active session (i.e. VT changes). + */ +Session * +seat_get_expected_active_session (Seat *seat) +{ + g_return_val_if_fail (seat != NULL, NULL); + return seat->priv->active_session; +} + +/** + * Sets the active session which lightdm expects to be active. + * + * This function is different from seat_set_active_session() in that the + * later performs an actual session activation, whereas this function just + * updates the active session after the session has been activated by some + * means external to lightdm (i.e. VT changes). + */ +void +seat_set_externally_activated_session (Seat *seat, Session *session) +{ + g_return_if_fail (seat != NULL); + if (seat->priv->active_session) + g_object_unref (seat->priv->active_session); + seat->priv->active_session = g_object_ref (session); +} + +Session * +seat_find_session_by_login1_id (Seat *seat, const gchar *login1_session_id) +{ + GList *session_link; + + for (session_link = seat->priv->sessions; session_link; session_link = session_link->next) + { + Session *session = session_link->data; + if (g_strcmp0 (login1_session_id, session_get_login1_session_id (session)) == 0) + return session; + } + + return NULL; +} + gboolean seat_get_can_switch (Seat *seat) { @@ -346,13 +394,15 @@ emit_upstart_signal (const gchar *signal) { g_return_if_fail (signal != NULL); g_return_if_fail (signal[0] != 0); + const gchar* argv[] = {"initctl", "-q", "emit", signal, "DISPLAY_MANAGER=lightdm", NULL}; if (getuid () != 0) return; - gchar *cmd = g_strdup_printf ("initctl -q emit %s DISPLAY_MANAGER=lightdm", signal); - g_spawn_command_line_async (cmd, NULL); /* OK if it fails, probably not installed */ - g_free (cmd); + /* OK if it fails, probably not installed or not running upstart */ + g_spawn_async (NULL, argv, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, NULL); } static void @@ -93,6 +93,12 @@ Session *seat_get_active_session (Seat *seat); Session *seat_get_next_session (Seat *seat); +void seat_set_externally_activated_session (Seat *seat, Session *session); + +Session *seat_get_expected_active_session (Seat *seat); + +Session *seat_find_session_by_login1_id (Seat *seat, const gchar *login1_session_id); + gboolean seat_get_can_switch (Seat *seat); gboolean seat_get_allow_guest (Seat *seat); diff --git a/src/session-child.c b/src/session-child.c index c6f8a7ce..e85f57da 100644 --- a/src/session-child.c +++ b/src/session-child.c @@ -243,7 +243,7 @@ session_child_run (int argc, char **argv) XAuthority *x_authority = NULL; gchar *x_authority_filename; GDBusConnection *bus; - const gchar *login1_session = NULL; + const gchar *login1_session_id = NULL; gchar *console_kit_cookie = NULL; const gchar *locale_value; gchar *locale_var; @@ -545,10 +545,10 @@ session_child_run (int argc, char **argv) } /* Check what logind session we are, or fallback to ConsoleKit */ - login1_session = pam_getenv (pam_handle, "XDG_SESSION_ID"); - if (login1_session) + login1_session_id = pam_getenv (pam_handle, "XDG_SESSION_ID"); + if (login1_session_id) { - write_string (login1_session); + write_string (login1_session_id); if (version >= 2) write_string (NULL); } @@ -768,7 +768,7 @@ session_child_run (int argc, char **argv) pam_close_session (pam_handle, 0); /* Remove credentials */ - result = pam_setcred (pam_handle, PAM_DELETE_CRED); + pam_setcred (pam_handle, PAM_DELETE_CRED); pam_end (pam_handle, 0); pam_handle = NULL; diff --git a/src/session.c b/src/session.c index 1ac16109..e25a69a5 100644 --- a/src/session.c +++ b/src/session.c @@ -653,6 +653,13 @@ session_get_username (Session *session) } const gchar * +session_get_login1_session_id (Session *session) +{ + g_return_val_if_fail (session != NULL, NULL); + return session->priv->login1_session_id; +} + +const gchar * session_get_console_kit_cookie (Session *session) { g_return_val_if_fail (session != NULL, NULL); @@ -903,6 +910,8 @@ session_init (Session *session) { session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate); session->priv->log_filename = g_strdup (".xsession-errors"); + session->priv->to_child_input = -1; + session->priv->from_child_output = -1; } static void @@ -917,6 +926,8 @@ session_finalize (GObject *object) g_object_unref (self->priv->display_server); if (self->priv->pid) kill (self->priv->pid, SIGKILL); + close (self->priv->to_child_input); + close (self->priv->from_child_output); if (self->priv->from_child_channel) g_io_channel_unref (self->priv->from_child_channel); if (self->priv->from_child_watch) diff --git a/src/session.h b/src/session.h index 513fd12d..c62303e6 100644 --- a/src/session.h +++ b/src/session.h @@ -115,6 +115,8 @@ gboolean session_get_is_started (Session *session); const gchar *session_get_username (Session *session); +const gchar *session_get_login1_session_id (Session *session); + const gchar *session_get_console_kit_cookie (Session *session); void session_respond (Session *session, struct pam_response *response); diff --git a/src/unity-system-compositor.c b/src/unity-system-compositor.c index 03824284..f4b74eb1 100644 --- a/src/unity-system-compositor.c +++ b/src/unity-system-compositor.c @@ -147,7 +147,8 @@ write_message (UnitySystemCompositor *compositor, guint16 id, const guint8 *payl data[1] = id & 0xFF; data[2] = payload_length >> 8; data[3] = payload_length & 0xFF; - memcpy (data + 4, payload, payload_length); + if (payload) + memcpy (data + 4, payload, payload_length); errno = 0; if (write (compositor->priv->to_compositor_pipe[1], data, data_length) != data_length) diff --git a/src/xdmcp-protocol.c b/src/xdmcp-protocol.c index eb5517fb..f45e7aeb 100644 --- a/src/xdmcp-protocol.c +++ b/src/xdmcp-protocol.c @@ -10,8 +10,10 @@ */ #include <string.h> +#include <gio/gio.h> #include "xdmcp-protocol.h" +#include "x-authority.h" typedef struct { @@ -481,13 +483,31 @@ xdmcp_packet_tostring (XDMCPPacket *packet) t3 = g_string_new (""); for (i = 0; i < packet->Request.n_connections; i++) { - gchar *t4; + XDMCPConnection *connection = &packet->Request.connections[i]; + GSocketFamily family = G_SOCKET_FAMILY_INVALID; if (i != 0) g_string_append (t3, " "); - t4 = data_tostring (&packet->Request.connections[i].address); - g_string_append_printf (t3, "(%d, %s)", packet->Request.connections[i].type, t4); - g_free (t4); + + if (connection->type == XAUTH_FAMILY_INTERNET && connection->address.length == 4) + family = G_SOCKET_FAMILY_IPV4; + else if (connection->type == XAUTH_FAMILY_INTERNET6 && connection->address.length == 16) + family = G_SOCKET_FAMILY_IPV6; + + if (family != G_SOCKET_FAMILY_INVALID) + { + GInetAddress *address = g_inet_address_new_from_bytes (connection->address.data, family); + gchar *t4 = g_inet_address_to_string (address); + g_string_append (t3, t4); + g_free (t4); + g_object_unref (address); + } + else + { + gchar *t4 = data_tostring (&connection->address); + g_string_append_printf (t3, "(%d, %s)", connection->type, t4); + g_free (t4); + } } string = g_strdup_printf ("Request(display_number=%d connections=[%s] authentication_name='%s' authentication_data=%s authorization_names=[%s] manufacturer_display_id='%s')", packet->Request.display_number, t3->str, packet->Request.authentication_name, t2, diff --git a/src/xdmcp-server.c b/src/xdmcp-server.c index d92b57d9..197dbc11 100644 --- a/src/xdmcp-server.c +++ b/src/xdmcp-server.c @@ -277,10 +277,76 @@ decode_key (const gchar *key, guint8 *data) } } +static GInetAddress * +connection_to_address (XDMCPConnection *connection) +{ + switch (connection->type) + { + case XAUTH_FAMILY_INTERNET: + if (connection->address.length == 4) + return g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4); + else + return NULL; + case XAUTH_FAMILY_INTERNET6: + if (connection->address.length == 16) + return g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6); + else + return NULL; + default: + return NULL; + } +} + +static gssize +find_address (GInetAddress **addresses, gsize length, GSocketFamily family) +{ + int i; + + for (i = 0; i < length; i++) + { + GInetAddress *address = addresses[i]; + if (address && g_inet_address_get_family (address) == family) + return i; + } + + return -1; +} + +static XDMCPConnection * +choose_connection (XDMCPPacket *packet, GInetAddress *source_address) +{ + GInetAddress **addresses; + gsize addresses_length, i; + gssize index = -1; + + addresses_length = packet->Request.n_connections; + addresses = malloc (sizeof (GInetAddress *) * addresses_length); + for (i = 0; i < addresses_length; i++) + addresses[i] = connection_to_address (&packet->Request.connections[i]); + + /* Use the address the request came in on as this is the least likely to have firewall / routing issues */ + for (i = 0; i < addresses_length && index < 0; i++) + if (g_inet_address_equal (source_address, addresses[i])) + index = i; + + /* Otherwise try and find an address that matches the incoming type */ + if (index < 0) + index = find_address (addresses, addresses_length, g_inet_address_get_family (source_address)); + + /* Otherwise use the first available */ + if (index < 0 && addresses_length > 0) + index = 0; + + for (i = 0; i < addresses_length; i++) + g_object_unref (addresses[i]); + g_free (addresses); + + return &packet->Request.connections[index]; +} + static void handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet) { - int i; XDMCPPacket *response; XDMCPSession *session; guint8 *authentication_data = NULL; @@ -292,48 +358,15 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X guint8 *session_authorization_data = NULL; gsize session_authorization_data_length = 0; gchar **j; - guint16 family; - GInetAddress *x_server_address = NULL; + XDMCPConnection *connection; gchar *display_number; XdmAuthKeyRec rho; - /* Try and find an IPv6 address */ - for (i = 0; i < packet->Request.n_connections; i++) - { - XDMCPConnection *connection = &packet->Request.connections[i]; - if (connection->type == XAUTH_FAMILY_INTERNET6 && connection->address.length == 16) - { - family = connection->type; - x_server_address = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6); - - /* We can't use link-local addresses, as we need to know what interface it is on */ - if (g_inet_address_get_is_link_local (x_server_address)) - { - g_object_unref (x_server_address); - x_server_address = NULL; - } - else - break; - } - } - - /* If no IPv6 address, then try and find an IPv4 one */ - if (!x_server_address) - { - for (i = 0; i < packet->Request.n_connections; i++) - { - XDMCPConnection *connection = &packet->Request.connections[i]; - if (connection->type == XAUTH_FAMILY_INTERNET && connection->address.length == 4) - { - family = connection->type; - x_server_address = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4); - break; - } - } - } + /* Choose an address to connect back on */ + connection = choose_connection (packet, g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address))); /* Decline if haven't got an address we can connect on */ - if (!x_server_address) + if (!connection) { response = xdmcp_packet_alloc (XDMCP_Decline); response->Decline.status = g_strdup ("No valid address found"); @@ -449,34 +482,34 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X } session = add_session (server); - session->priv->address = x_server_address; + session->priv->address = connection_to_address (connection); session->priv->display_number = packet->Request.display_number; display_number = g_strdup_printf ("%d", packet->Request.display_number); /* We need to check if this is the loopback address and set the authority * for a local connection if this is so as XCB treats "127.0.0.1" as local * always */ - if (g_inet_address_get_is_loopback (x_server_address)) + if (g_inet_address_get_is_loopback (session->priv->address)) { gchar hostname[1024]; gethostname (hostname, 1024); session->priv->authority = x_authority_new (XAUTH_FAMILY_LOCAL, - (guint8 *) hostname, - strlen (hostname), - display_number, - authorization_name, - session_authorization_data, - session_authorization_data_length); + (guint8 *) hostname, + strlen (hostname), + display_number, + authorization_name, + session_authorization_data, + session_authorization_data_length); } else - session->priv->authority = x_authority_new (family, - g_inet_address_to_bytes (G_INET_ADDRESS (x_server_address)), - g_inet_address_get_native_size (G_INET_ADDRESS (x_server_address)), - display_number, - authorization_name, - session_authorization_data, - session_authorization_data_length); + session->priv->authority = x_authority_new (connection->type, + connection->address.data, + connection->address.length, + display_number, + authorization_name, + session_authorization_data, + session_authorization_data_length); g_free (display_number); response = xdmcp_packet_alloc (XDMCP_Accept); |