Sophie

Sophie

distrib > Mageia > 5 > x86_64 > media > core-release-src > by-pkgid > d951c9cf0cb0a1339c22e98d1e4186b4 > files > 2

caja-1.8.2-4.mga5.src.rpm

AUTHOR: Atilla ÖNTAŞ <tarakbumba@gmail.com> 2015-04-05

Based on patches by Martin Pitt <martin.pitt@ubuntu.com>, 
https://git.gnome.org/browse/gnome-settings-daemon/commit/?id=71deedf732a0fa52a58407c271c764f851cb6f57 by Cosimo Cecchi
and Martin Pitt

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 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 GNOME screen saver is currently locked. https://bugzilla.gnome.org/show_bug.cgi?id=642020

Index: caja-1.8.2/src/caja-application.c
===================================================================
--- caja-1.8.2/src/caja-application.c
+++ caja-1.8.2/src/caja-application.c	2015-04-29 00:14:53.985126262 +0300
@@ -122,7 +122,10 @@
 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,
@@ -362,7 +365,18 @@
 
     g_object_unref (application->unique_app);
 
-    if (application->automount_idle_id != 0)
+	if (application->ss_watch_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;
@@ -374,6 +388,12 @@
         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);
 }
 
@@ -554,6 +574,180 @@
 }
 
 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)
 {
@@ -601,7 +795,11 @@
     /* 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 */
 
@@ -616,6 +814,8 @@
                              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);
 
@@ -1477,6 +1677,34 @@
 }
 
 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)
@@ -1485,7 +1713,7 @@
             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
     {
Index: caja-1.8.2/src/caja-application.h
===================================================================
--- caja-1.8.2/src/caja-application.h
+++ caja-1.8.2/src/caja-application.h	2015-04-29 00:14:53.991126120 +0300
@@ -66,6 +66,10 @@
     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