summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortarakbumba <[email protected]>2015-04-07 00:07:27 +0300
committertarakbumba <[email protected]>2015-04-07 00:07:27 +0300
commitadc45ec84298f6246d9ed219607bb5c169f50e08 (patch)
treef4a74caaaa94c09ea1b951c4a6874b23c144e0ea
parent304866dd42e3ec1d8f1694f42c69af247a772330 (diff)
downloadcaja-adc45ec84298f6246d9ed219607bb5c169f50e08.tar.bz2
caja-adc45ec84298f6246d9ed219607bb5c169f50e08.tar.xz
Fix for https://github.com/mate-desktop/caja/issues/398
On the Shmoocon at 2011 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 on 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 MATE screen saver is currently locked. See also https://bugzilla.gnome.org/show_bug.cgi?id=642020 This commit is merely based on : https://git.gnome.org/browse/nautilus/commit/?h=gnome-2-32&id=b7262fa945ef1ea936c15f0d248ad7a024d97dca
-rw-r--r--src/caja-application.c232
-rw-r--r--src/caja-application.h4
2 files changed, 232 insertions, 4 deletions
diff --git a/src/caja-application.c b/src/caja-application.c
index 02c1c3dc..1eb2a7cb 100644
--- a/src/caja-application.c
+++ b/src/caja-application.c
@@ -120,7 +120,10 @@ static void mount_added_callback (GVolumeMonitor *mo
static void volume_added_callback (GVolumeMonitor *monitor,
GVolume *volume,
CajaApplication *application);
-static void drive_connected_callback (GVolumeMonitor *monitor,
+static void volume_removed_callback (GVolumeMonitor *monitor,
+ GVolume *volume,
+ CajaApplication *application);
+ static void drive_connected_callback (GVolumeMonitor *monitor,
GDrive *drive,
CajaApplication *application);
static void drive_listen_for_eject_button (GDrive *drive,
@@ -360,7 +363,14 @@ caja_application_finalize (GObject *object)
g_object_unref (application->unique_app);
- if (application->automount_idle_id != 0)
+ 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;
@@ -372,6 +382,12 @@ caja_application_finalize (GObject *object)
fdb_manager = NULL;
}
+ if (application->ss_proxy != NULL)
+ {
+ g_object_unref (application->ss_proxy);
+ application->ss_proxy = NULL;
+ }
+
G_OBJECT_CLASS (caja_application_parent_class)->finalize (object);
}
@@ -552,6 +568,180 @@ out:
}
static void
+check_volume_queue (CajaApplication *application)
+{
+ GList *l, *next;
+ GVolume *volume;
+
+ l = application->volume_queue;
+
+ if (application->screensaver_active)
+ {
+ return;
+ }
+
+ while (l != NULL) {
+ volume = l->data;
+ next = l->next;
+
+ caja_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.mate.ScreenSaver"
+#define SCREENSAVER_PATH "/org/mate/ScreenSaver"
+#define SCREENSAVER_INTERFACE "org.mate.ScreenSaver"
+
+static void
+screensaver_signal_callback (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ CajaApplication *application = user_data;
+
+ if (g_strcmp0 (signal_name, "ActiveChanged") == 0)
+ {
+ g_variant_get (parameters, "(b)", &application->screensaver_active);
+ g_debug ("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)
+{
+ CajaApplication *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);
+
+ g_debug ("Screensaver GetActive() returned %d", application->screensaver_active);
+}
+
+static void
+screensaver_proxy_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CajaApplication *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;
+ }
+
+ g_debug ("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)
+{
+ CajaApplication *application = user_data;
+
+ g_debug ("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)
+{
+ CajaApplication *application = user_data;
+
+ g_debug ("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 (CajaApplication *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 (CajaApplication *application,
gboolean no_desktop)
{
@@ -599,7 +789,11 @@ finish_startup (CajaApplication *application,
/* Initialize the desktop link monitor singleton */
caja_desktop_link_monitor_get ();
- /* Watch for mounts so we can restore open windows This used
+ /* Initialize MATE 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 */
@@ -614,6 +808,8 @@ finish_startup (CajaApplication *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);
@@ -1475,6 +1671,34 @@ window_can_be_closed (CajaWindow *window)
}
static void
+check_screen_lock_and_mount (CajaApplication *application,
+ GVolume *volume)
+{
+ if (application->screensaver_active)
+ {
+ /* queue the volume, to mount it after the screensaver state changed */
+ g_debug ("Queuing volume %p", volume);
+ application->volume_queue = g_list_prepend (application->volume_queue,
+ g_object_ref (volume));
+ } else {
+ /* mount it immediately */
+ caja_file_operations_mount_volume (NULL, volume, TRUE);
+ }
+}
+
+static void
+volume_removed_callback (GVolumeMonitor *monitor,
+ GVolume *volume,
+ CajaApplication *application)
+{
+ g_debug ("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,
CajaApplication *application)
@@ -1483,7 +1707,7 @@ volume_added_callback (GVolumeMonitor *monitor,
g_volume_should_automount (volume) &&
g_volume_can_mount (volume))
{
- caja_file_operations_mount_volume (NULL, volume, TRUE);
+ check_screen_lock_and_mount (application, volume);
}
else
{
diff --git a/src/caja-application.h b/src/caja-application.h
index 27cd8e18..699083a8 100644
--- a/src/caja-application.h
+++ b/src/caja-application.h
@@ -66,6 +66,10 @@ typedef struct
EggSMClient* smclient;
GVolumeMonitor* volume_monitor;
unsigned int automount_idle_id;
+ gboolean screensaver_active;
+ guint ss_watch_id;
+ GDBusProxy *ss_proxy;
+ GList *volume_queue;
} CajaApplication;
typedef struct