Help with strings for "solution" for desktop file "virus" problem



So, there has been a lot of attention on the internets recently about
the the desktop file "virus" issue.

I think its all pretty overblown, and any solution we have that doesn't
completely neuter the feature will just involve users learning to work
around the issue in cases where this is correct, and thus are likely to
do this when they are targets of an actual attack.

However, I do agree that it is a bit bad that you can be a target of an
attack like this without really being able to realize it. So, my current
plan is two-fold:

1) Only detect desktop files with .desktop extension. I.e. we never
sniff them for files with no or an invalid extension.

2) Unless the desktop file is in a system directory or has the execute
bit set we don't show the custom icon and display name for the desktop
file. (Instead we show the real filename, which will always be *.desktop
per 1 above, and the standard "shortcut" icon.)

Furthermore, when you lauch a non-trusted desktop file we open a dialog
where giving some info, plus letting you launch it, mark it executable
(if you have the perms) or cancel.

I have implemented and commited 1) in gio. A patch for 2) is attached.
However, I would like some help/feedback on what exactly the dialog
should say. Its kinda tricky to describe this in a sane way without
claiming things that can be legitimate are viruses.

Currently the Dialog says:

 Untrusted application launcher
 The file %s is an application launcher, but it is not marked trusted.  
 If you recieved this file from an unknown source or did not expect it
 to be an application launcher it may be unsafe to launch.

 [_Launch anyway] [Mark as _Trusted] [[Cancel]]

I don't feel this is a great wording, but I don't have any better ideas.
Maybe some native english speaker could help out?

Index: libnautilus-private/nautilus-directory-async.c
===================================================================
--- libnautilus-private/nautilus-directory-async.c	(revision 14953)
+++ libnautilus-private/nautilus-directory-async.c	(working copy)
@@ -3571,6 +3571,50 @@ file_info_start (NautilusDirectory *dire
 	g_object_unref (location);
 }
 
+static gboolean
+is_link_trusted (NautilusFile *file,
+		 gboolean is_launcher)
+{
+	gboolean res;
+	
+	if (!is_launcher) {
+		return TRUE;
+	}
+	
+	if (nautilus_file_can_execute (file)) {
+		return TRUE;
+	}
+
+	res = FALSE;
+	
+	if (nautilus_file_is_local (file)) {
+		const char * const * data_dirs; 
+		char *uri, *path;
+		int i;
+			
+		data_dirs = g_get_system_data_dirs ();
+		
+		path = NULL;
+		uri = nautilus_file_get_uri (file);
+		if (uri) {
+			path = g_filename_from_uri (uri, NULL, NULL);
+			g_free (uri);
+		}
+
+		for (i = 0; path != NULL && data_dirs[i] != NULL; i++) {
+			if (g_str_has_prefix (path, data_dirs[i])) {
+				res = TRUE;
+				break;
+			}
+			
+		}
+		g_free (path);
+	}
+	
+	
+	return res;
+}
+
 static void
 link_info_done (NautilusDirectory *directory,
 		NautilusFile *file,
@@ -3580,12 +3624,21 @@ link_info_done (NautilusDirectory *direc
 		gboolean is_launcher,
 		gboolean is_foreign)
 {
+	gboolean is_trusted;
+	
 	file->details->link_info_is_up_to_date = TRUE;
 
-	nautilus_file_set_display_name (file, name, name, TRUE);
+	is_trusted = is_link_trusted (file, is_launcher);
+
+	if (is_trusted) {
+		nautilus_file_set_display_name (file, name, name, TRUE);
+	} else {
+		nautilus_file_set_display_name (file, NULL, NULL, TRUE);
+	}
 	
 	file->details->got_link_info = TRUE;
 	g_free (file->details->custom_icon);
+	file->details->custom_icon = NULL;
 	if (uri) {
 		if (file->details->activation_location) {
 			g_object_unref (file->details->activation_location);
@@ -3594,9 +3647,12 @@ link_info_done (NautilusDirectory *direc
 		file->details->got_custom_activation_location = TRUE;
 		file->details->activation_location = g_file_new_for_uri (uri);
 	}
-	file->details->custom_icon = g_strdup (icon);
+	if (is_trusted) {
+		file->details->custom_icon = g_strdup (icon);
+	}
 	file->details->is_launcher = is_launcher;
 	file->details->is_foreign_link = is_foreign;
+	file->details->is_trusted_link = is_trusted;
 	
 	nautilus_directory_async_state_changed (directory);
 }
Index: libnautilus-private/nautilus-mime-actions.c
===================================================================
--- libnautilus-private/nautilus-mime-actions.c	(revision 14953)
+++ libnautilus-private/nautilus-mime-actions.c	(working copy)
@@ -27,6 +27,7 @@
 
 #include <eel/eel-glib-extensions.h>
 #include <eel/eel-stock-dialogs.h>
+#include <eel/eel-alert-dialog.h>
 #include <eel/eel-string.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
@@ -83,6 +84,7 @@ typedef struct {
 #define RESPONSE_RUN 1000
 #define RESPONSE_DISPLAY 1001
 #define RESPONSE_RUN_IN_TERMINAL 1002
+#define RESPONSE_MARK_TRUSTED 1003
 
 #define SILENT_WINDOW_OPEN_LIMIT 5
 
@@ -1044,6 +1046,7 @@ activate_parameters_install_free (Activa
 	if (parameters_install->parent_window) {
 		g_object_remove_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *)&parameters_install->parent_window);
 	}
+	nautilus_file_unref (parameters_install->file);
 	nautilus_file_list_free (parameters_install->files);
 	g_free (parameters_install->activation_directory);
 	g_free (parameters_install);
@@ -1266,6 +1269,142 @@ out:
 	g_free (error_message);
 }
 
+typedef struct {
+	GtkWindow *parent_window;
+	NautilusFile *file;
+} ActivateParametersDesktop;
+
+static void
+activate_parameters_desktop_free (ActivateParametersDesktop *parameters_desktop)
+{
+	if (parameters_desktop->parent_window) {
+		g_object_remove_weak_pointer (G_OBJECT (parameters_desktop->parent_window), (gpointer *)&parameters_desktop->parent_window);
+	}
+	nautilus_file_unref (parameters_desktop->file);
+	g_free (parameters_desktop);
+}
+
+static void
+mark_trusted_callback (NautilusFile  *file,
+		       GFile         *result_location,
+		       GError        *error,
+		       gpointer       callback_data)
+{
+	ActivateParametersDesktop *parameters;
+
+	parameters = callback_data;
+	if (error) {
+		eel_show_error_dialog (_("Unable to mark launcher trusted (executable)"),
+				       error->message,
+				       parameters->parent_window);
+	}
+	
+	activate_parameters_desktop_free (parameters);
+}
+
+static void
+untrusted_launcher_response_callback (GtkDialog *dialog,
+				      int response_id,
+				      ActivateParametersDesktop *parameters)
+{
+	GdkScreen *screen;
+	char *uri;
+	gboolean free_params;
+	
+	free_params = TRUE;
+	switch (response_id) {
+	case RESPONSE_RUN:
+		screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
+		uri = nautilus_file_get_uri (parameters->file);
+		nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+				    "directory view activate_callback launch_desktop_file window=%p: %s",
+				    parameters->parent_window, uri);
+		nautilus_launch_desktop_file (screen, uri, NULL,
+					      parameters->parent_window);
+		g_free (uri);
+		break;
+	case RESPONSE_MARK_TRUSTED:
+		nautilus_file_set_permissions (parameters->file, 
+					       nautilus_file_get_permissions (parameters->file) | S_IXGRP | S_IXUSR | S_IXOTH,
+					       mark_trusted_callback,
+					       parameters);
+		free_params = FALSE;
+		break;
+	default:
+		/* Just destroy dialog */
+		break;
+	}
+	
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	if (free_params) {
+		activate_parameters_desktop_free (parameters);
+	}
+}
+
+static void
+activate_desktop_file (ActivateParameters *parameters,
+		       NautilusFile *file)
+{
+	ActivateParametersDesktop *parameters_desktop;
+	char *primary, *secondary, *display_name;
+	GtkWidget *dialog;
+	GdkScreen *screen;
+	char *uri;
+	
+	screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
+
+	if (!nautilus_file_is_trusted_link (file)) {
+		/* copy the parts of parameters we are interested in as the orignal will be freed */
+		parameters_desktop = g_new0 (ActivateParametersDesktop, 1);
+		if (parameters->parent_window) {
+			parameters_desktop->parent_window = parameters->parent_window;
+			g_object_add_weak_pointer (G_OBJECT (parameters_desktop->parent_window), (gpointer *)&parameters_desktop->parent_window);
+		}
+		parameters_desktop->file = nautilus_file_ref (file);
+
+		primary = _("Untrusted application launcher");
+		display_name = nautilus_file_get_display_name (file);
+		secondary =
+			g_strdup_printf (_("The file %s is an application launcher, but it is not marked trusted. "
+					   "If you recieved this file from an unknown source or did not expect it to be an application launcher it may be unsafe to launch."
+					   ),
+					 display_name);
+		
+		dialog = eel_alert_dialog_new (parameters->parent_window,
+					       0,
+					       GTK_MESSAGE_WARNING,
+					       GTK_BUTTONS_NONE,
+					       primary,
+					       secondary);
+		gtk_dialog_add_button (GTK_DIALOG (dialog),
+				       _("_Launch anyway"), RESPONSE_RUN);
+		if (nautilus_file_can_set_permissions (file)) {
+			gtk_dialog_add_button (GTK_DIALOG (dialog),
+					       _("Mark as _Trusted"), RESPONSE_MARK_TRUSTED);
+		}
+		gtk_dialog_add_button (GTK_DIALOG (dialog),
+				       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+		gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+		g_signal_connect (dialog, "response",
+				  G_CALLBACK (untrusted_launcher_response_callback),
+				  parameters_desktop);
+		gtk_widget_show (dialog);
+		
+		g_free (display_name);
+		g_free (secondary);
+		return;
+	}
+	
+	uri = nautilus_file_get_uri (file);
+	nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+			    "directory view activate_callback launch_desktop_file window=%p: %s",
+			    parameters->parent_window, uri);
+	nautilus_launch_desktop_file (screen, uri, NULL,
+				      parameters->parent_window);
+	g_free (uri);
+}
+
 static void
 activate_files (ActivateParameters *parameters)
 {
@@ -1340,14 +1479,8 @@ activate_files (ActivateParameters *para
 	launch_desktop_files = g_list_reverse (launch_desktop_files);
 	for (l = launch_desktop_files; l != NULL; l = l->next) {
 		file = NAUTILUS_FILE (l->data);
-		
-		uri = nautilus_file_get_uri (file);
-		nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
-				    "directory view activate_callback launch_desktop_file window=%p: %s",
-				    parameters->parent_window, uri);
-		nautilus_launch_desktop_file (screen, uri, NULL,
-					      parameters->parent_window);
-		g_free (uri);
+
+		activate_desktop_file (parameters, file);
 	}
 
 	old_working_dir = NULL;
Index: libnautilus-private/nautilus-file-private.h
===================================================================
--- libnautilus-private/nautilus-file-private.h	(revision 14953)
+++ libnautilus-private/nautilus-file-private.h	(working copy)
@@ -198,6 +198,7 @@ struct NautilusFileDetails
 	eel_boolean_bit has_open_window               : 1;
 
 	eel_boolean_bit is_launcher                   : 1;
+	eel_boolean_bit is_trusted_link               : 1;
 	eel_boolean_bit is_foreign_link               : 1;
 	eel_boolean_bit is_symlink                    : 1;
 	eel_boolean_bit is_mountpoint                 : 1;
Index: libnautilus-private/nautilus-file.c
===================================================================
--- libnautilus-private/nautilus-file.c	(revision 14953)
+++ libnautilus-private/nautilus-file.c	(working copy)
@@ -195,14 +195,6 @@ nautilus_file_set_display_name (Nautilus
 {
 	gboolean changed;
 
-	if (display_name == NULL || *display_name == 0) {
-		return FALSE;
-	}
-	
-	if (!custom && file->details->got_custom_display_name) {
-		return FALSE;
-	}
-
 	if (custom && display_name == NULL) {
 		/* We're re-setting a custom display name, invalidate it if
 		   we already set it so that the old one is re-read */
@@ -213,6 +205,14 @@ nautilus_file_set_display_name (Nautilus
 		}
 		return FALSE;
 	}
+	
+	if (display_name == NULL || *display_name == 0) {
+		return FALSE;
+	}
+	
+	if (!custom && file->details->got_custom_display_name) {
+		return FALSE;
+	}
 
 	if (edit_name == NULL) {
 		edit_name = display_name;
@@ -295,6 +295,7 @@ nautilus_file_clear_info (NautilusFile *
 	
 	file->details->is_launcher = FALSE;
 	file->details->is_foreign_link = FALSE;
+	file->details->is_trusted_link = FALSE;
 	file->details->is_symlink = FALSE;
 	file->details->is_hidden = FALSE;
 	file->details->is_backup = FALSE;
@@ -3175,6 +3176,12 @@ nautilus_file_is_foreign_link (NautilusF
 }
 
 gboolean
+nautilus_file_is_trusted_link (NautilusFile *file)
+{
+	return file->details->is_trusted_link;
+}
+
+gboolean
 nautilus_file_has_activation_uri (NautilusFile *file)
 {
 	return file->details->activation_location != NULL;
Index: libnautilus-private/nautilus-file.h
===================================================================
--- libnautilus-private/nautilus-file.h	(revision 14953)
+++ libnautilus-private/nautilus-file.h	(working copy)
@@ -399,6 +399,7 @@ GList                  *nautilus_file_li
  */
 gboolean                nautilus_file_is_launcher                       (NautilusFile                   *file);
 gboolean                nautilus_file_is_foreign_link                   (NautilusFile                   *file);
+gboolean                nautilus_file_is_trusted_link                   (NautilusFile                   *file);
 gboolean                nautilus_file_has_activation_uri                (NautilusFile                   *file);
 char *                  nautilus_file_get_activation_uri                (NautilusFile                   *file);
 GFile *                 nautilus_file_get_activation_location           (NautilusFile                   *file);


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