Repository: freedomofpress/securedrop

Issue:
SecureDrop desktop shortcuts not displayed correctly on Tails 3.3   
# Bug

The desktop shortcuts for the SecureDrop Source and Journalist interfaces do not show the correct title and logo on Tail 3.3. Tails 3.3 introduces a fix for the `.desktop` file security issue. The fix requires `.desktop` files to have a `trusted` metadata parameter set before the `.desktop` file is parsed and displayed with a custom name and icon.

The shortcuts are displayed with a name like `source.desktop` and requires a user to click "Trust and Launch" before the shortcut is displayed with the correct name and icon. Requiring users to click-through this warning could cause warning fatigue and result in unsafe user behavior.

## Steps to reproduce

Click a SecureDrop .desktop shortcut on a Journalist Workstation running Tails 3.3. 

## Expected Behavior

The SecureDrop .onion opens in Tor Browser.

## Actual Behavior

The user receives a warning about an untrusted .desktop file.

## Comments

The SecureDrop `tails-config` Ansible role should set the Nautilus `metadata::trusted` parameter for both the Source and Journalist .desktop files.



Discussion:
Thanks for filing @DonnchaC. We need to run `gio set name_of_file.desktop metadata::trusted yes` for each desktop shortcut. This metadata won't persist so this needs to be executed at the start of the Tails session.  
Hey @kushaldas and @emkll since y'all are going to take a look at fixing this for 0.5 - recall that in the [tails-config](https://github.com/freedomofpress/securedrop/tree/develop/install_files/ansible-base/roles/tails-config) role, we have [`securedrop_init.py`](https://github.com/freedomofpress/securedrop/blob/develop/install_files/ansible-base/roles/tails-config/files/securedrop_init.py) to persist state in the journalist/admin workstations. That would be a good place to add the `gio` command from [this comment](https://github.com/freedomofpress/securedrop/issues/2586#issuecomment-345347652). 
I tried manually run the `gio` command on a given desktop file, it still kept asking me to trust the desktop file first.

On the other hand, the verified Tails 3.3 ISO failed to boot after installation from a USB device in a VM. `initramfs` fails to find any bootable live image. It boots from the ISO perfect. 
I will submit a small python code based PR for the [`securedrop_init.py`](https://github.com/freedomofpress/securedrop/blob/develop/install_files/ansible-base/roles/tails-config/files/securedrop_init.py), but first I have to find a better to verify that the given commands as it is supposed to be.
@kushaldas I had the same problem: It seems like the metadata doesn't get applied to the `~/Desktop/source.desktop` or `~/Desktop/journalist.desktop` (because of symlink?) One needs to edit the metadata of `/lib/live/mount/persistence/TailsData_unlocked/dotfiles/Desktop/` and recreate the symlinks on the Desktop.
@emkll I was trying on a real file on the Desktop directory in my test.
Finally found the issue into my code.

For the record, this [`commit`](https://github.com/GNOME/nautilus/commit/1630f53481f445ada0a455e9979236d31a8d3bb0#diff-6ebec3ec1dc762c0942fac693d5f07f5R1520) has the formal fix in the upstream Nautilus code.

For any new desktop file, I had to follow two steps.
`gio set source.desktop metadata::trusted yes` and the `chmod +x source.desktop`.

This also explains the comment about setting the metadata on the real link instead of the symlink, as `gio` generally follows the symlink as I understand.
One other issue I've encountered is that these commands throw an error when you are uid 0, which is the privileges with which `securedrop_init.py` runs. The only times I've successfully set the `.desktop` file as trusted was with the `amnesia` user.
The commands I have mentioned above will work for any directory except `~/Desktop`. Following is from a chat with the upstream developer of Nautilus.

```
<csoriano> I have the feeling I know what's going on... the desktop files you see in the ui desktop are not actually desktop files
<csoriano> it's a custom made weird nice thing we do because desktop is great :)
<csoriano> so maybe we are failing to sync the metadata for files in the ~/Desktop
... 
<csoriano> kushal: I guess there are two bugs, one that the desktop fails to sync because it's using the weird NautilusLink files (emulating actual files) and the other in regular folders in some cases it fails to sync the metadata.
```
I have filed the upstream bug [here](https://gitlab.gnome.org/GNOME/nautilus/issues/131). This [comment](https://github.com/GNOME/nautilus/commit/1630f53481f445ada0a455e9979236d31a8d3bb0#diff-6ebec3ec1dc762c0942fac693d5f07f5R1537) in the source explains why this is not a problem when we double click and mark as trusted. Sadly this can not be done by any command.

#### Possible solution

* Do the steps before Nautilus comes up (may not be possible using the `securedrop_init.py` script).
* Kill current nautilus-desktop process and then relaunch it.
* Ask the journalists to press F5 to refresh the desktop before anything else.

I will try out the options now, and update this issue as I find out more details.
@kushaldas I got it to work by deleting and re-creating the symlink. If you run this as `amnesia` and not sudo:
```
subprocess.call(['rm', '/home/amnesia/Desktop/source.desktop'])
subprocess.call(['ln', '-s', '/lib/live/mount/persistence/TailsData_unlocked/dotfiles/Desktop/source.desktop', '/home/amnesia/Desktop/source.desktop'])
subprocess.call(['gio', 'set', '/home/amnesia/Desktop/source.desktop', 'metadata::trusted', 'yes'])
```
Rebooting and following the steps mentioned in the above comment is not working for me. If you have marked the file trusted once, and then if you remove and follow the rest of the steps, then it will work. After reboot we are back to the same old untrusted desktop files.
@kushaldas I seem to have made both progress and regression (see https://github.com/freedomofpress/securedrop/tree/tails_3.3_desktop_icons), it seems like environment variables are required to set the metadata.

Resolving patch:
diff --git a/install_files/ansible-base/roles/tails-config/files/securedrop_init.py b/install_files/ansible-base/roles/tails-config/files/securedrop_init.py
--- a/install_files/ansible-base/roles/tails-config/files/securedrop_init.py
+++ b/install_files/ansible-base/roles/tails-config/files/securedrop_init.py
@@ -1,6 +1,8 @@
 #!/usr/bin/python
 
+import grp
 import os
+import pwd
 import sys
 import subprocess
 
@@ -13,6 +15,8 @@
 path_torrc_additions = '/home/amnesia/Persistent/.securedrop/torrc_additions'
 path_torrc_backup = '/etc/tor/torrc.bak'
 path_torrc = '/etc/tor/torrc'
+path_desktop = '/home/amnesia/Desktop/'
+path_persistent_desktop = '/lib/live/mount/persistence/TailsData_unlocked/dotfiles/Desktop/'
 
 # load torrc_additions
 if os.path.isfile(path_torrc_additions):
@@ -48,7 +52,29 @@
                  '/org/gnome/nautilus/preferences/automatic-decompression',
                  'false'])
 
-# notify the user
+# Set journalist.desktop and source.desktop links as trusted with Nautilus (see
+# https://github.com/freedomofpress/securedrop/issues/2586)
+# set euid and env variables to amnesia user
+amnesia_gid = grp.getgrnam('amnesia').gr_gid
+amnesia_uid = pwd.getpwnam('amnesia').pw_uid
+os.setresgid(amnesia_gid, amnesia_gid, -1)
+os.setresuid(amnesia_uid, amnesia_uid, -1)
+env = os.environ.copy()
+env['XDG_RUNTIME_DIR'] = '/run/user/{}'.format(amnesia_uid)
+env['XDG_DATA_DIR'] = '/usr/share/gnome:/usr/local/share/:/usr/share/'
+env['HOME'] = '/home/amnesia'
+env['LOGNAME'] = 'amnesia'
+env['DBUS_SESSION_BUS_ADDRESS'] = 'unix:path=/run/user/{}/bus'.format(amnesia_uid)
+
+# remove existing shortcut, recreate symlink and change metadata attribute to trust .desktop
+for shortcut in ['source.desktop', 'journalist.desktop']:
+    subprocess.call(['rm', path_desktop + shortcut], env=env)
+    subprocess.call(['ln', '-s', path_persistent_desktop + shortcut, path_desktop + shortcut], env=env)
+    subprocess.call(['gio', 'set', path_desktop + shortcut, 'metadata::trusted', 'yes'], env=env)
+
+# reacquire uid0 and notify the user
+os.setresuid(0,0,-1)
+os.setresgid(0,0,-1)
 subprocess.call(['tails-notify-user',
                  'SecureDrop successfully auto-configured!',
                  'You can now access the Journalist Interface.\nIf you are an admin, you can now SSH to the servers.'])


Test patch: