Commit 102bfe59 authored by Michael Terry's avatar Michael Terry

Handle running pkexec better -- more safely write environment variables to...

Handle running pkexec better -- more safely write environment variables to disk and use a nice message instead of asking to run /bin/sh
parent ddcec718
......@@ -65,5 +65,12 @@ deja_dup_appdata = custom_target('org.gnome.DejaDup.appdata.xml',
test('validate-appstream', appstream_util,
args: ['--nonet', 'validate-relax', deja_dup_appdata.full_path()])
conf_data = configuration_data()
conf_data.set('pkglibexecdir', pkglibexecdir)
vars = configure_file(input: '',
output: 'org.gnome.DejaDup.policy',
configuration: conf_data,
install_dir: join_paths(datadir, 'polkit-1', 'actions'))
message('You may need to recompile your gsettings schemas or regenerate
your icon cache after installation.')
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
<action id="org.gnome.DejaDup.duplicity">
<description gettext-domain="deja-dup">Restore</description>
<message gettext-domain="deja-dup">Privileges are required to restore files to system locations</message>
<annotate key="org.freedesktop.policykit.exec.path">@pkglibexecdir@/duplicity</annotate>
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2017-08-09 15:43-0400\n"
"POT-Creation-Date: 2017-08-10 01:31-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <>\n"
......@@ -106,10 +106,7 @@ internal class DuplicityInstance : Object
// Add logging argument
if (as_root) {
// Make log file
int logfd = 0;
string logname;
logfd = FileUtils.open_tmp(Config.PACKAGE + "-XXXXXX", out logname);
logfile = File.new_for_path(logname);
logfile = File.new_tmp(Config.PACKAGE + "-XXXXXX", out logstream);
else {
......@@ -136,38 +133,19 @@ internal class DuplicityInstance : Object
// Run as root if needed
if (as_root &&
Environment.find_program_in_path("pkexec") != null &&
Environment.find_program_in_path("sh") != null) {
// pkexec does not preserve environment variables, so we need to stuff
// the ones we care about in a shell script.
string scriptname;
var scriptfd = FileUtils.open_tmp(Config.PACKAGE + "-XXXXXX", out scriptname);
scriptfile = File.new_for_path(scriptname);
// We have to wrap all current args into one string.
StringBuilder args = new StringBuilder();
// Set environment variables for subprocess here because sudo reserves
Environment.find_program_in_path("pkexec") != null) {
// Set environment variables for subprocess here because pkexec reserves
// the right to strip them.
StringBuilder args = new StringBuilder();
foreach (string env in envp_in)
args.append("export '%s'\n".printf(env));
foreach (string a in argv) {
if (a == null)
if (args.len == 0)
args.append(" " + Shell.quote(a));
FileUtils.set_contents(scriptname, args.str);
argv = new List<string>(); // reset
IOStream iostream;
scriptfile = File.new_tmp(Config.PACKAGE + "-XXXXXX", out iostream);
yield iostream.get_output_stream().write_all_async(, Priority.DEFAULT, null, null);
argv.prepend(Path.build_filename(Config.PKG_LIBEXEC_DIR, "duplicity"));
......@@ -235,6 +213,7 @@ internal class DuplicityInstance : Object
int[] pipes;
DataInputStream reader;
File logfile;
IOStream logstream;
File scriptfile;
bool process_done;
int status;
......@@ -334,22 +313,15 @@ internal class DuplicityInstance : Object
* Stream initiated either from log file or pipe
try {
InputStream stream;
if (logfile != null)
stream = yield logfile.read_async(Priority.DEFAULT, null);
stream = new UnixInputStream(pipes[0], true);
reader = new DataInputStream(stream);
catch (Error e) {
warning("%s\n", e.message);
done(false, false);
InputStream stream;
if (logstream != null)
stream = logstream.get_input_stream();
stream = new UnixInputStream(pipes[0], true);
reader = new DataInputStream(stream);
// This loop goes on while rest of class is doing its work. We ref
// it to make sure that the rest of the class doesn't drop from under us.
# -*- Mode: sh; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-
# This file is part of Déjà Dup.
# For copyright information, see AUTHORS.
# Déjà Dup is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# Déjà Dup is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with Déjà Dup. If not, see <>.
# This script *could* just be a symlink to '/bin/sh' and do the same thing.
# But since this script is meant to be called by pkexec to operate as root,
# it didn't seem smart to install a polkit action that gave /bin/sh an
# innocent description that could be called by other programs.
# However, we should be mindful of attacks here and quote everything carefully.
set -e
# The first argument is going to be a file to read and export some variables
# from. We do this in a file to avoid any environment variables being listed
# on the command line (and visible from 'ps') and because pkexec will strip
# our environment before we see them normally.
# The second argument is "duplicity"
# All other arguments are for duplicity.
while read line; do
case "$line" in
export "$line"
# Do not echo it here, else someone could read any file via this
echo "Invalid environment variable passed"
exit 1
done < "$1"
[ "$1" = "duplicity" ] || exit 1
# PATH should be made safe by pkexec, so let's find duplicity on system
exec "$@"
......@@ -35,3 +35,9 @@ configure_file(
input: 'duplicity.plugin',
output: 'duplicity.plugin',
install_dir: toolsdir)
# This is used when running duplicity as root.
# See data/ and DuplicityInstance.vala for more details.
install_dir: pkglibexecdir,
install_mode: 'rwxr-xr-x')
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: deja-dup\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-08-09 15:43-0400\n"
"POT-Creation-Date: 2017-08-10 01:31-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <>\n"
......@@ -23,7 +23,7 @@ msgstr ""
#. context is itself a reference to both the underlying command line tool
#. "duplicity" and the act of duplicating data for backup. As a whole, the
#. phrase "Déjà Dup" may not be very translatable.
#: data/ deja-dup/main.vala:295
#: data/ deja-dup/main.vala:304
#: libdeja/CommonUtils.vala:145
msgid "Déjà Dup Backup Tool"
msgstr ""
......@@ -62,7 +62,7 @@ msgid "Integrates well into your GNOME desktop"
msgstr ""
#. Translators: "Backups" is a noun
#: data/org.gnome.DejaDup.desktop:5 deja-dup/main.vala:159
#: data/org.gnome.DejaDup.desktop:5 deja-dup/main.vala:160
#: deja-dup/Prompt.vala:78
msgid "Backups"
msgstr ""
......@@ -432,6 +432,14 @@ msgid ""
"If the backup location is on an external volume, this is the volume’s icon."
msgstr ""
#: data/ deja-dup/AssistantRestore.vala:68
msgid "Restore"
msgstr ""
#: data/
msgid "Privileges are required to restore files to system locations"
msgstr ""
#. Translators: Monitor in this sense means something akin to 'watcher', not
#. a computer screen. This program acts like a daemon that kicks off
#. backups at scheduled times.
......@@ -633,10 +641,6 @@ msgstr ""
msgid "Backup encryption password"
msgstr ""
#: deja-dup/AssistantRestore.vala:68
msgid "Restore"
msgstr ""
#: deja-dup/AssistantRestore.vala:69
msgid "_Restore"
msgstr ""
......@@ -819,47 +823,47 @@ msgstr ""
msgid "_Resume Later"
msgstr ""
#: deja-dup/main.vala:30 deja-dup/monitor/monitor.vala:34
#: deja-dup/main.vala:31 deja-dup/monitor/monitor.vala:34
msgid "Show version"
msgstr ""
#: deja-dup/main.vala:31
#: deja-dup/main.vala:32
msgid "Restore given files"
msgstr ""
#: deja-dup/main.vala:32
#: deja-dup/main.vala:33
msgid "Immediately start a backup"
msgstr ""
#: deja-dup/main.vala:34
#: deja-dup/main.vala:35
msgid "Restore deleted files"
msgstr ""
#: deja-dup/main.vala:80 deja-dup/main.vala:95 deja-dup/main.vala:121
#: deja-dup/main.vala:81 deja-dup/main.vala:96 deja-dup/main.vala:122
msgid "An operation is already in progress"
msgstr ""
#: deja-dup/main.vala:100
#: deja-dup/main.vala:101
msgid "No directory provided"
msgstr ""
#: deja-dup/main.vala:104
#: deja-dup/main.vala:105
msgid "Only one directory can be shown at once"
msgstr ""
#: deja-dup/main.vala:110
#: deja-dup/main.vala:111
msgid "Directory does not exist"
msgstr ""
#: deja-dup/main.vala:114
#: deja-dup/main.vala:115
msgid "You must provide a directory, not a file"
msgstr ""
#: deja-dup/main.vala:128
#: deja-dup/main.vala:129
msgid "Scheduled backup delayed"
msgstr ""
#: deja-dup/main.vala:221
#: deja-dup/main.vala:230
msgid "translator-credits"
msgstr ""
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment