[nautilus/gnome-2-32] disable automounting while screen is locked



commit b7262fa945ef1ea936c15f0d248ad7a024d97dca
Author: Martin Pitt <martin pitt ubuntu com>
Date:   Tue Feb 22 14:06:14 2011 +0100

    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

 src/nautilus-application.c |  228 +++++++++++++++++++++++++++++++++++++++++++-
 src/nautilus-application.h |    5 +
 2 files changed, 232 insertions(+), 1 deletions(-)
---
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 08407a5..dfeaea6 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 36e53b6..d558932 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 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]