summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2011-02-22 14:06:14 +0100
committerMartin Pitt <martin.pitt@ubuntu.com>2011-02-24 19:18:43 +0100
commitb7262fa945ef1ea936c15f0d248ad7a024d97dca (patch)
tree5c195d16611233f65952ded8ae02c6a7db36b31d
parentb68cab2a5b6eabe4836b6b56e867dbd4435fafaf (diff)
downloadnautilus-b7262fa945ef1ea936c15f0d248ad7a024d97dca.tar.gz
disable automounting while screen is locked
On the recent Shmoocon there was a presentation by Jon Larimer demonstrating how to abuse vulnerabilities and bugs, or even just creating socially or security compromising thumbnails in mounting and thumbnailing, which happens o automounting USB drives. This is a particular issue when this happens on a locked box where the attacker doesn't otherwise have access to the user account: http://www.net-security.org/secworld.php?id=10544 Disable automounting if the GNOME screen saver is currently locked. Backported from gnome-settings-daemon trunk commits 71deedf7 and 90c0f8676. https://bugzilla.gnome.org/show_bug.cgi?id=642020
-rw-r--r--src/nautilus-application.c228
-rw-r--r--src/nautilus-application.h5
2 files changed, 232 insertions, 1 deletions
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 08407a5f0..dfeaea6d2 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -116,6 +116,9 @@ static void mount_added_callback (GVolumeMonitor *mo
static void volume_added_callback (GVolumeMonitor *monitor,
GVolume *volume,
NautilusApplication *application);
+static void volume_removed_callback (GVolumeMonitor *monitor,
+ GVolume *volume,
+ NautilusApplication *application);
static void drive_connected_callback (GVolumeMonitor *monitor,
GDrive *drive,
NautilusApplication *application);
@@ -347,6 +350,13 @@ nautilus_application_finalize (GObject *object)
g_object_unref (application->unique_app);
+ g_bus_unwatch_name (application->ss_watch_id);
+
+ if (application->volume_queue != NULL) {
+ g_list_free_full (application->volume_queue, g_object_unref);
+ application->volume_queue = NULL;
+ }
+
if (application->automount_idle_id != 0) {
g_source_remove (application->automount_idle_id);
application->automount_idle_id = 0;
@@ -357,6 +367,11 @@ nautilus_application_finalize (GObject *object)
application->proxy = NULL;
}
+ if (application->ss_proxy != NULL) {
+ g_object_unref (application->ss_proxy);
+ application->ss_proxy = NULL;
+ }
+
G_OBJECT_CLASS (nautilus_application_parent_class)->finalize (object);
}
@@ -663,6 +678,182 @@ do_initialize_consolekit (NautilusApplication *application)
}
static void
+check_volume_queue (NautilusApplication *application)
+{
+ GList *l, *next;
+ GVolume *volume;
+
+ l = application->volume_queue;
+
+ if (application->screensaver_active) {
+ return;
+ }
+
+ while (l != NULL) {
+ volume = l->data;
+ next = l->next;
+
+ nautilus_file_operations_mount_volume (NULL, volume, TRUE);
+ application->volume_queue =
+ g_list_remove (application->volume_queue, volume);
+
+ g_object_unref (volume);
+ l = next;
+ }
+
+ application->volume_queue = NULL;
+}
+
+#define SCREENSAVER_NAME "org.gnome.ScreenSaver"
+#define SCREENSAVER_PATH "/org/gnome/ScreenSaver"
+#define SCREENSAVER_INTERFACE "org.gnome.ScreenSaver"
+
+static void
+screensaver_signal_callback (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ NautilusApplication *application = user_data;
+
+ if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
+ g_variant_get (parameters, "(b)", &application->screensaver_active);
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "Screensaver active changed to %d",
+ application->screensaver_active);
+
+ check_volume_queue (application);
+ }
+}
+
+static void
+screensaver_get_active_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NautilusApplication *application = user_data;
+ GDBusProxy *proxy = application->ss_proxy;
+ GVariant *result;
+ GError *error = NULL;
+
+ result = g_dbus_proxy_call_finish (proxy,
+ res,
+ &error);
+
+ if (error != NULL) {
+ g_warning ("Can't call GetActive() on the ScreenSaver object: %s",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ g_variant_get (result, "(b)", &application->screensaver_active);
+ g_variant_unref (result);
+
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "Screensaver GetActive() returned %d",
+ application->screensaver_active);
+}
+
+static void
+screensaver_proxy_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NautilusApplication *application = user_data;
+ GError *error = NULL;
+ GDBusProxy *ss_proxy;
+
+ ss_proxy = g_dbus_proxy_new_finish (res, &error);
+
+ if (error != NULL) {
+ g_warning ("Can't get proxy for the ScreenSaver object: %s",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "ScreenSaver proxy ready");
+
+ application->ss_proxy = ss_proxy;
+
+ g_signal_connect (ss_proxy, "g-signal",
+ G_CALLBACK (screensaver_signal_callback), application);
+
+ g_dbus_proxy_call (ss_proxy,
+ "GetActive",
+ NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1,
+ NULL,
+ screensaver_get_active_ready_cb,
+ application);
+}
+
+static void
+screensaver_appeared_callback (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ NautilusApplication *application = user_data;
+
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "ScreenSaver name appeared");
+
+ application->screensaver_active = FALSE;
+
+ g_dbus_proxy_new (connection,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ name,
+ SCREENSAVER_PATH,
+ SCREENSAVER_INTERFACE,
+ NULL,
+ screensaver_proxy_ready_cb,
+ application);
+}
+
+static void
+screensaver_vanished_callback (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ NautilusApplication *application = user_data;
+
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "ScreenSaver name vanished");
+
+ application->screensaver_active = FALSE;
+ g_object_unref (&application->ss_proxy);
+
+ /* in this case force a clear of the volume queue, without
+ * mounting them.
+ */
+ if (application->volume_queue != NULL) {
+ g_list_free_full (application->volume_queue, g_object_unref);
+ application->volume_queue = NULL;
+ }
+}
+
+static void
+do_initialize_screensaver (NautilusApplication *application)
+{
+ application->ss_watch_id =
+ g_bus_watch_name (G_BUS_TYPE_SESSION,
+ SCREENSAVER_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ screensaver_appeared_callback,
+ screensaver_vanished_callback,
+ application,
+ NULL);
+}
+
+static void
do_upgrades_once (NautilusApplication *application,
gboolean no_desktop)
{
@@ -709,6 +900,10 @@ finish_startup (NautilusApplication *application,
/* Initialize the ConsoleKit listener for active session */
do_initialize_consolekit (application);
+ /* Initialize GNOME screen saver listener to control automount
+ * permission */
+ do_initialize_screensaver (application);
+
/* Watch for mounts so we can restore open windows This used
* to be for showing new window on mount, but is not used
* anymore */
@@ -724,6 +919,8 @@ finish_startup (NautilusApplication *application,
G_CALLBACK (mount_added_callback), application, 0);
g_signal_connect_object (application->volume_monitor, "volume_added",
G_CALLBACK (volume_added_callback), application, 0);
+ g_signal_connect_object (application->volume_monitor, "volume_removed",
+ G_CALLBACK (volume_removed_callback), application, 0);
g_signal_connect_object (application->volume_monitor, "drive_connected",
G_CALLBACK (drive_connected_callback), application, 0);
@@ -1520,6 +1717,35 @@ window_can_be_closed (NautilusWindow *window)
}
static void
+check_screen_lock_and_mount (NautilusApplication *application,
+ GVolume *volume)
+{
+ if (application->screensaver_active) {
+ /* queue the volume, to mount it after the screensaver state changed */
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "Queuing volume %p", volume);
+ application->volume_queue = g_list_prepend (application->volume_queue,
+ g_object_ref (volume));
+ } else {
+ /* mount it immediately */
+ nautilus_file_operations_mount_volume (NULL, volume, TRUE);
+ }
+}
+
+static void
+volume_removed_callback (GVolumeMonitor *monitor,
+ GVolume *volume,
+ NautilusApplication *application)
+{
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "Volume %p removed, removing from the queue", volume);
+
+ /* clear it from the queue, if present */
+ application->volume_queue =
+ g_list_remove (application->volume_queue, volume);
+}
+
+static void
volume_added_callback (GVolumeMonitor *monitor,
GVolume *volume,
NautilusApplication *application)
@@ -1527,7 +1753,7 @@ volume_added_callback (GVolumeMonitor *monitor,
if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT) &&
g_volume_should_automount (volume) &&
g_volume_can_mount (volume)) {
- nautilus_file_operations_mount_volume (NULL, volume, TRUE);
+ check_screen_lock_and_mount (application, volume);
} else {
/* Allow nautilus_autorun() to run. When the mount is later
* added programmatically (i.e. for a blank CD),
diff --git a/src/nautilus-application.h b/src/nautilus-application.h
index 36e53b6b4..d558932c2 100644
--- a/src/nautilus-application.h
+++ b/src/nautilus-application.h
@@ -68,6 +68,11 @@ typedef struct {
unsigned int automount_idle_id;
GDBusProxy *proxy;
gboolean session_is_active;
+
+ gboolean screensaver_active;
+ guint ss_watch_id;
+ GDBusProxy *ss_proxy;
+ GList *volume_queue;
} NautilusApplication;
typedef struct {