Skip to content

Commit

Permalink
Add secure desktop file launching (bug #5012).
Browse files Browse the repository at this point in the history
Only allow direct execution of desktop files in an XDG
directory and if they are executable.
  • Loading branch information
nschermer committed Oct 3, 2012
1 parent 5c2bf77 commit 1ec8ff8
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 124 deletions.
1 change: 1 addition & 0 deletions thunar/thunar-chooser-dialog.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ thunar_chooser_dialog_response (GtkDialog *widget,
/* create launch context */
context = gdk_app_launch_context_new ();
gdk_app_launch_context_set_screen (context, gtk_widget_get_screen (GTK_WIDGET (dialog)));
gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());

/* create fake file list */
list.data = thunar_file_get_file (dialog->file); list.next = list.prev = NULL;
Expand Down
102 changes: 102 additions & 0 deletions thunar/thunar-dialogs.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,3 +731,105 @@ thunar_dialogs_show_job_error (GtkWindow *parent,
g_string_free (primary, TRUE);
}



gboolean
thunar_dialogs_show_insecure_program (gpointer parent,
const gchar *primary,
ThunarFile *file,
const gchar *command)
{
GdkScreen *screen;
GtkWindow *window;
gint response;
GtkWidget *dialog;
GString *secondary;
ThunarFileMode old_mode;
ThunarFileMode new_mode;
GFileInfo *info;
GError *err = NULL;

_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
_thunar_return_val_if_fail (g_utf8_validate (command, -1, NULL), FALSE);

/* parse the parent window and screen */
screen = thunar_util_parse_parent (parent, &window);

/* secondary text */
secondary = g_string_new (NULL);
g_string_append_printf (secondary, _("The desktop file \"%s\" is in an insecure location "
"and not marked as executable. If you do not trust "
"this program, click Cancel."),
thunar_file_get_display_name (file));
g_string_append (secondary, "\n\n");
if (exo_str_looks_like_an_uri (command))
g_string_append_printf (secondary, G_KEY_FILE_DESKTOP_KEY_URL"=%s", command);
else
g_string_append_printf (secondary, G_KEY_FILE_DESKTOP_KEY_EXEC"=%s", command);

/* allocate and display the error message dialog */
dialog = gtk_message_dialog_new (window,
GTK_DIALOG_MODAL |
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_NONE,
"%s", primary);
gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Launch Anyway"), GTK_RESPONSE_OK);
if (thunar_file_is_chmodable (file))
gtk_dialog_add_button (GTK_DIALOG (dialog), _("Mark _Executable"), GTK_RESPONSE_APPLY);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
if (screen != NULL && window == NULL)
gtk_window_set_screen (GTK_WINDOW (dialog), screen);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", secondary->str);
g_string_free (secondary, TRUE);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);

/* check if we should make the file executable */
if (response == GTK_RESPONSE_APPLY)
{
/* try to query information about the file */
info = g_file_query_info (thunar_file_get_file (file),
G_FILE_ATTRIBUTE_UNIX_MODE,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, &err);

if (G_LIKELY (info != NULL))
{
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE))
{
/* determine the current mode */
old_mode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);

/* generate the new mode */
new_mode = old_mode | THUNAR_FILE_MODE_USR_EXEC | THUNAR_FILE_MODE_GRP_EXEC | THUNAR_FILE_MODE_OTH_EXEC;

if (old_mode != new_mode)
{
g_file_set_attribute_uint32 (thunar_file_get_file (file),
G_FILE_ATTRIBUTE_UNIX_MODE, new_mode,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, &err);
}
}
else
{
g_warning ("No %s attribute found", G_FILE_ATTRIBUTE_UNIX_MODE);
}

g_object_unref (info);
}

if (err != NULL)
{
thunar_dialogs_show_error (parent, err, ("Unable to mark launcher executable"));
g_error_free (err);
}

/* just launch */
response = GTK_RESPONSE_OK;
}

return (response == GTK_RESPONSE_OK);
}
45 changes: 22 additions & 23 deletions thunar/thunar-dialogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,28 @@

G_BEGIN_DECLS;

ThunarJob *thunar_dialogs_show_rename_file (gpointer parent,
ThunarFile *file);

void thunar_dialogs_show_about (GtkWindow *parent,
const gchar *title,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);

void thunar_dialogs_show_error (gpointer parent,
const GError *error,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);

ThunarJobResponse thunar_dialogs_show_job_ask (GtkWindow *parent,
const gchar *question,
ThunarJobResponse choices);

ThunarJobResponse thunar_dialogs_show_job_ask_replace (GtkWindow *parent,
ThunarFile *src_file,
ThunarFile *dst_file);

void thunar_dialogs_show_job_error (GtkWindow *parent,
GError *error);
ThunarJob *thunar_dialogs_show_rename_file (gpointer parent,
ThunarFile *file);
void thunar_dialogs_show_about (GtkWindow *parent,
const gchar *title,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);
void thunar_dialogs_show_error (gpointer parent,
const GError *error,
const gchar *format,
...) G_GNUC_PRINTF (3, 4);
ThunarJobResponse thunar_dialogs_show_job_ask (GtkWindow *parent,
const gchar *question,
ThunarJobResponse choices);
ThunarJobResponse thunar_dialogs_show_job_ask_replace (GtkWindow *parent,
ThunarFile *src_file,
ThunarFile *dst_file);
void thunar_dialogs_show_job_error (GtkWindow *parent,
GError *error);
gboolean thunar_dialogs_show_insecure_program (gpointer parent,
const gchar *title,
ThunarFile *file,
const gchar *command);

G_END_DECLS;

Expand Down
2 changes: 1 addition & 1 deletion thunar/thunar-dnd.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ thunar_dnd_perform (GtkWidget *widget,
else if (thunar_file_is_executable (file))
{
/* TODO any chance to determine the working dir here? */
succeed = thunar_file_execute (file, NULL, gtk_widget_get_screen (widget), file_list, &error);
succeed = thunar_file_execute (file, NULL, widget, file_list, &error);
if (G_UNLIKELY (!succeed))
{
/* display an error to the user */
Expand Down
Loading

0 comments on commit 1ec8ff8

Please sign in to comment.