On 21/11/2016 01:49, LyX Ticket Tracker wrote:
Comment (by t.cucinotta):
Just worked out new separate patch-set for the cross-OS needauth security
option for converters (asking users if they really know what they're about
to be doing). Added further global option that forbids use anyway, unless
user goes and unchecks it in the prefs.
New patch is available in my user repo tommaso, branch features/needauth-
converters
Please, find attached the pseudo-final patch. I would push it to master, unless
there are objections / further comments for improvements.
Note: the AppArmor stuff would come afterwards as a separate patch-set.
Thanks,
T.
>From cf0addda455879609aa42995d7c48327bcaf8f76 Mon Sep 17 00:00:00 2001
From: Tommaso Cucinotta <tomm...@lyx.org>
Date: Sat, 5 Nov 2016 01:00:44 +0100
Subject: [PATCH 1/4] Add needauth option to converters that need explicit user
authorization before being run.
Addressing #10481.
Converters marked with the new "needauth" option won't be run unless
the user gives explicit authorization, which is asked on-demand when
the converter is about to be run (question is not asked if the file is
cached and the converter is not needed).
The user prompt has a 3rd button (yes to all for document) so that
he/she's not prompted again for the same converter over the same document
(identified through buffer->filePath()).
---
lib/configure.py | 28 ++++++++++++++--------------
src/Converter.cpp | 27 ++++++++++++++++++++++++++-
src/Converter.h | 8 ++++++++
src/graphics/GraphicsConverter.cpp | 10 ++++++++++
4 files changed, 58 insertions(+), 15 deletions(-)
diff --git a/lib/configure.py b/lib/configure.py
index a11050fb..b282a284 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -749,8 +749,8 @@ def checkConverterEntries():
rc_entry = [r'''\converter latex lyx "%% -f $$i $$o" ""
\converter latexclipboard lyx "%% -fixedenc utf8 -f $$i $$o" ""
\converter literate lyx "%% -n -m noweb -f $$i $$o" ""
-\converter sweave lyx "%% -n -m sweave -f $$i $$o" ""
-\converter knitr lyx "%% -n -m knitr -f $$i $$o" ""'''], not_found = 'tex2lyx')
+\converter sweave lyx "%% -n -m sweave -f $$i $$o" "needauth"
+\converter knitr lyx "%% -n -m knitr -f $$i $$o" "needauth"'''], not_found = 'tex2lyx')
if path == '':
logger.warning("Failed to find tex2lyx on your system.")
@@ -763,24 +763,24 @@ def checkConverterEntries():
\converter literate dviluatex "%%" ""'''])
#
checkProg('a Sweave -> LaTeX converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxsweave.R $$p$$i $$p$$o $$e $$r'],
- rc_entry = [r'''\converter sweave latex "%%" ""
-\converter sweave pdflatex "%%" ""
-\converter sweave xetex "%%" ""
-\converter sweave luatex "%%" ""
-\converter sweave dviluatex "%%" ""'''])
+ rc_entry = [r'''\converter sweave latex "%%" "needauth"
+\converter sweave pdflatex "%%" "needauth"
+\converter sweave xetex "%%" "needauth"
+\converter sweave luatex "%%" "needauth"
+\converter sweave dviluatex "%%" "needauth"'''])
#
checkProg('a knitr -> LaTeX converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxknitr.R $$p$$i $$p$$o $$e $$r'],
- rc_entry = [r'''\converter knitr latex "%%" ""
-\converter knitr pdflatex "%%" ""
-\converter knitr xetex "%%" ""
-\converter knitr luatex "%%" ""
-\converter knitr dviluatex "%%" ""'''])
+ rc_entry = [r'''\converter knitr latex "%%" "needauth"
+\converter knitr pdflatex "%%" "needauth"
+\converter knitr xetex "%%" "needauth"
+\converter knitr luatex "%%" "needauth"
+\converter knitr dviluatex "%%" "needauth"'''])
#
checkProg('a Sweave -> R/S code converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxstangle.R $$i $$e $$r'],
- rc_entry = [ r'\converter sweave r "%%" ""' ])
+ rc_entry = [ r'\converter sweave r "%%" "needauth"' ])
#
checkProg('a knitr -> R/S code converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxknitr.R $$p$$i $$p$$o $$e $$r tangle'],
- rc_entry = [ r'\converter knitr r "%%" ""' ])
+ rc_entry = [ r'\converter knitr r "%%" "needauth"' ])
#
checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex',
'htmltolatex -input $$i -output $$o', 'htmltolatex.jar -input $$i -output $$o'],
diff --git a/src/Converter.cpp b/src/Converter.cpp
index 58e486e6..02631ca4 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -100,7 +100,7 @@ Converter::Converter(string const & f, string const & t,
string const & c, string const & l)
: from_(f), to_(t), command_(c), flags_(l),
From_(0), To_(0), latex_(false), xml_(false),
- need_aux_(false), nice_(false)
+ need_aux_(false), nice_(false), need_auth_(false)
{}
@@ -128,6 +128,8 @@ void Converter::readFlags()
parselog_ = flag_value;
else if (flag_name == "nice")
nice_ = true;
+ else if (flag_name == "needauth")
+ need_auth_ = true;
}
if (!result_dir_.empty() && result_file_.empty())
result_file_ = "index." + formats.extension(to_);
@@ -402,6 +404,29 @@ bool Converters::convert(Buffer const * buffer,
"tmpfile.out"));
}
+ if (conv.need_auth()) {
+ static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
+ int choice;
+ if (buffer) {
+ std::string const & fname = buffer->filePath();
+ if (auth_files.find(fname) == auth_files.end()) {
+ choice = frontend::Alert::prompt(
+ _("Launch of external converter needs user authorization"), bformat(_(securityWarning), from_utf8(conv.command())),
+ 0, 0, _("&No"), _("&Yes"), _("Yes, &and do not ask again for document"));
+ if (choice == 2)
+ auth_files.insert(fname);
+ } else {
+ choice = 1;
+ }
+ } else {
+ choice = frontend::Alert::prompt(
+ _("Need user authorization to launch external converter"), bformat(_(securityWarning), from_utf8(conv.command())),
+ 0, 0, _("&No"), _("&Yes"));
+ }
+ if (choice == 0)
+ return false;
+ }
+
if (conv.latex()) {
run_latex = true;
string command = conv.command();
diff --git a/src/Converter.h b/src/Converter.h
index c9c44238..9bde8714 100644
--- a/src/Converter.h
+++ b/src/Converter.h
@@ -70,6 +70,8 @@ public:
///
bool need_aux() const { return need_aux_; }
///
+ bool need_auth() const { return need_auth_; }
+ ///
bool nice() const { return nice_; }
///
std::string const result_dir() const { return result_dir_; }
@@ -77,6 +79,7 @@ public:
std::string const result_file() const { return result_file_; }
///
std::string const parselog() const { return parselog_; }
+
private:
///
trivstring from_;
@@ -101,6 +104,8 @@ private:
bool need_aux_;
/// we need a "nice" file from the backend, c.f. OutputParams.nice.
bool nice_;
+ /// Use of this converter needs explicit user authorization
+ bool need_auth_;
/// If the converter put the result in a directory, then result_dir
/// is the name of the directory
trivstring result_dir_;
@@ -181,6 +186,7 @@ public:
const_iterator end() const { return converterlist_.end(); }
///
void buildGraph();
+
private:
///
FormatList const
@@ -210,6 +216,8 @@ private:
bool copy);
///
Graph G_;
+ /// set of files authorized for external conversion
+ std::set<std::string> auth_files;
};
/// The global instance.
diff --git a/src/graphics/GraphicsConverter.cpp b/src/graphics/GraphicsConverter.cpp
index 67b1580f..6017073f 100644
--- a/src/graphics/GraphicsConverter.cpp
+++ b/src/graphics/GraphicsConverter.cpp
@@ -15,6 +15,7 @@
#include "Converter.h"
#include "Format.h"
+#include "frontends/alert.h"
#include "support/lassert.h"
#include "support/convert.h"
#include "support/debug.h"
@@ -372,6 +373,15 @@ static void build_script(string const & from_file,
outfile = tempfile.name().toFilesystemEncoding();
}
+ if (conv.need_auth()) {
+ static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
+ docstring const & question = bformat(from_utf8(securityWarning), from_utf8(conv.command()));
+ int choice = frontend::Alert::prompt(
+ from_utf8("Need user authorization to launch external converter"), question, 0, 0, from_utf8("&No"), from_utf8("&Yes"));
+ if (choice == 0)
+ return;
+ }
+
// Store these names in the python script
script << "infile = "
<< quoteName(infile, quote_python) << "\n"
--
2.9.3
>From f51b10557547ea038a4823f5c6d87fcb63907a1b Mon Sep 17 00:00:00 2001
From: Tommaso Cucinotta <tomm...@lyx.org>
Date: Fri, 11 Nov 2016 22:27:11 +0100
Subject: [PATCH 2/4] Build document file-name awareness in GraphicsConverter.
Needed to complete [aa5311d5/lyxgit], while addressing #10481.
---
src/Buffer.cpp | 5 ++--
src/Buffer.h | 3 ++
src/Converter.h | 2 ++
src/factory.cpp | 2 +-
src/frontends/qt4/GuiExternal.cpp | 1 +
src/graphics/GraphicsCache.cpp | 4 +--
src/graphics/GraphicsCache.h | 2 +-
src/graphics/GraphicsCacheItem.cpp | 24 ++++++++-------
src/graphics/GraphicsCacheItem.h | 2 +-
src/graphics/GraphicsConverter.cpp | 41 +++++++++++++++++--------
src/graphics/GraphicsConverter.h | 3 +-
src/graphics/GraphicsLoader.cpp | 38 +++++++++++++++++-------
src/graphics/GraphicsLoader.h | 12 ++++----
src/graphics/PreviewImage.cpp | 8 ++++-
src/graphics/PreviewImage.h | 3 ++
src/graphics/PreviewLoader.cpp | 61 +++++++++++++++++++-------------------
src/insets/RenderGraphic.cpp | 2 ++
17 files changed, 135 insertions(+), 78 deletions(-)
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 8efa53bb..4facf094 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -79,6 +79,7 @@
#include "mathed/MathMacroTemplate.h"
#include "mathed/MathSupport.h"
+#include "graphics/GraphicsCache.h"
#include "graphics/PreviewLoader.h"
#include "frontends/alert.h"
@@ -421,8 +422,8 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
ignore_parent(false), toc_backend(owner), macro_lock(false), timestamp_(0),
checksum_(0), wa_(0), gui_(0), undo_(*owner), bibinfo_cache_valid_(false),
bibfile_cache_valid_(false), cite_labels_valid_(false), preview_error_(false),
- inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer), clone_list_(0),
- doing_export(false), parent_buffer(0),
+ inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
+ clone_list_(0), doing_export(false), parent_buffer(0),
word_count_(0), char_count_(0), blank_count_(0)
{
if (!cloned_buffer_) {
diff --git a/src/Buffer.h b/src/Buffer.h
index 477a8ac8..0cb70266 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -74,6 +74,7 @@ class FileNameList;
namespace graphics {
class PreviewLoader;
+class Cache;
}
@@ -587,6 +588,8 @@ public:
void updatePreviews() const;
/// Remove any previewed LaTeX snippets associated with this buffer
void removePreviews() const;
+ ///
+ graphics::Cache & graphicsCache() const;
/// Our main text (inside the top InsetText)
Text & text() const;
diff --git a/src/Converter.h b/src/Converter.h
index 9bde8714..34d8db70 100644
--- a/src/Converter.h
+++ b/src/Converter.h
@@ -186,6 +186,8 @@ public:
const_iterator end() const { return converterlist_.end(); }
///
void buildGraph();
+ ///
+ std::set<std::string> & authFiles() { return auth_files; }
private:
///
diff --git a/src/factory.cpp b/src/factory.cpp
index a03f88fa..9fdc37da 100644
--- a/src/factory.cpp
+++ b/src/factory.cpp
@@ -591,7 +591,7 @@ Inset * readInset(Lexer & lex, Buffer * buf)
return 0;
}
inset->setBuffer(*buf);
- } else {
+ } else {
// FIXME This branch should be made to use inset codes
// as the preceding branch does. Unfortunately, that
// will take some doing. It requires converting the
diff --git a/src/frontends/qt4/GuiExternal.cpp b/src/frontends/qt4/GuiExternal.cpp
index 2e7b6f63..e031f53e 100644
--- a/src/frontends/qt4/GuiExternal.cpp
+++ b/src/frontends/qt4/GuiExternal.cpp
@@ -14,6 +14,7 @@
#include "GuiExternal.h"
+#include "Buffer.h"
#include "FuncRequest.h"
#include "support/gettext.h"
#include "Length.h"
diff --git a/src/graphics/GraphicsCache.cpp b/src/graphics/GraphicsCache.cpp
index a51f2322..a3b8ebd3 100644
--- a/src/graphics/GraphicsCache.cpp
+++ b/src/graphics/GraphicsCache.cpp
@@ -101,7 +101,7 @@ vector<string> const & Cache::loadableFormats() const
}
-void Cache::add(FileName const & file) const
+void Cache::add(FileName const & file, FileName const & doc_file) const
{
// Is the file in the cache already?
if (inCache(file)) {
@@ -110,7 +110,7 @@ void Cache::add(FileName const & file) const
return;
}
- pimpl_->cache[file] = ItemPtr(new CacheItem(file));
+ pimpl_->cache[file] = ItemPtr(new CacheItem(file, doc_file));
}
diff --git a/src/graphics/GraphicsCache.h b/src/graphics/GraphicsCache.h
index 66cfc85b..0fd1dd01 100644
--- a/src/graphics/GraphicsCache.h
+++ b/src/graphics/GraphicsCache.h
@@ -46,7 +46,7 @@ public:
std::vector<std::string> const & loadableFormats() const;
/// Add a graphics file to the cache.
- void add(support::FileName const & file) const;
+ void add(support::FileName const & file, support::FileName const & doc_file) const;
/// Remove a file from the cache.
void remove(support::FileName const & file) const;
diff --git a/src/graphics/GraphicsCacheItem.cpp b/src/graphics/GraphicsCacheItem.cpp
index ea59173e..c698168d 100644
--- a/src/graphics/GraphicsCacheItem.cpp
+++ b/src/graphics/GraphicsCacheItem.cpp
@@ -14,6 +14,7 @@
#include "GraphicsCacheItem.h"
+#include "Buffer.h"
#include "GraphicsCache.h"
#include "GraphicsConverter.h"
#include "GraphicsImage.h"
@@ -42,7 +43,7 @@ class CacheItem::Impl : public boost::signals2::trackable {
public:
///
- Impl(FileName const & file);
+ Impl(FileName const & file, FileName const & doc_file);
/**
* If no file conversion is needed, then tryDisplayFormat() calls
@@ -93,6 +94,8 @@ public:
/// The filename we refer too.
FileName const filename_;
+ /// The document filename this graphic item belongs to
+ FileName const & doc_file_;
///
FileMonitor const monitor_;
@@ -125,8 +128,8 @@ public:
};
-CacheItem::CacheItem(FileName const & file)
- : pimpl_(new Impl(file))
+CacheItem::CacheItem(FileName const & file, FileName const & doc_file)
+ : pimpl_(new Impl(file,doc_file))
{}
@@ -204,8 +207,8 @@ boost::signals2::connection CacheItem::connect(slot_type const & slot) const
//------------------------------
-CacheItem::Impl::Impl(FileName const & file)
- : filename_(file),
+CacheItem::Impl::Impl(FileName const & file, FileName const & doc_file)
+ : filename_(file), doc_file_(doc_file),
monitor_(file, 2000),
zipped_(false),
remove_loaded_file_(false),
@@ -312,11 +315,10 @@ bool CacheItem::Impl::loadImage()
}
-static string const findTargetFormat(string const & from)
-{
- typedef vector<string> FormatList;
- FormatList const & formats = Cache::get().loadableFormats();
+typedef vector<string> FormatList;
+static string const findTargetFormat(FormatList const & formats, string const & from)
+{
// There must be a format to load from.
LASSERT(!formats.empty(), return string());
@@ -392,7 +394,7 @@ bool CacheItem::Impl::tryDisplayFormat(FileName & filename, string & from)
LYXERR(Debug::GRAPHICS, "\tCould not determine file format.");
}
LYXERR(Debug::GRAPHICS, "\n\tThe file contains " << from << " format data.");
- to_ = findTargetFormat(from);
+ to_ = findTargetFormat(Cache::get().loadableFormats(), from);
if (from == to_) {
// No conversion needed!
@@ -438,7 +440,7 @@ void CacheItem::Impl::convertToDisplayFormat()
// Connect a signal to this->imageConverted and pass this signal to
// the graphics converter so that we can load the modified file
// on completion of the conversion process.
- converter_ = make_unique<Converter>(filename, to_file_base.absFileName(),
+ converter_ = make_unique<Converter>(doc_file_, filename, to_file_base.absFileName(),
from, to_);
converter_->connect(bind(&Impl::imageConverted, this, _1));
converter_->startConversion();
diff --git a/src/graphics/GraphicsCacheItem.h b/src/graphics/GraphicsCacheItem.h
index 289b827a..ee2348d8 100644
--- a/src/graphics/GraphicsCacheItem.h
+++ b/src/graphics/GraphicsCacheItem.h
@@ -46,7 +46,7 @@ class Converter;
class CacheItem {
public:
///
- CacheItem(support::FileName const & file);
+ CacheItem(support::FileName const & file, support::FileName const & doc_file);
/// Needed for the pimpl
~CacheItem();
diff --git a/src/graphics/GraphicsConverter.cpp b/src/graphics/GraphicsConverter.cpp
index 6017073f..e12f6367 100644
--- a/src/graphics/GraphicsConverter.cpp
+++ b/src/graphics/GraphicsConverter.cpp
@@ -12,6 +12,7 @@
#include "GraphicsConverter.h"
+#include "Buffer.h"
#include "Converter.h"
#include "Format.h"
@@ -41,7 +42,7 @@ namespace graphics {
class Converter::Impl : public boost::signals2::trackable {
public:
///
- Impl(FileName const &, string const &, string const &, string const &);
+ Impl(FileName const &, FileName const &, string const &, string const &, string const &);
///
void startConversion();
@@ -61,6 +62,8 @@ public:
SignalType finishedConversion;
///
+ FileName const & doc_fname_;
+ ///
string script_command_;
///
FileName script_file_;
@@ -80,9 +83,10 @@ bool Converter::isReachable(string const & from_format_name,
}
-Converter::Converter(FileName const & from_file, string const & to_file_base,
+Converter::Converter(FileName const & doc_fname,
+ FileName const & from_file, string const & to_file_base,
string const & from_format, string const & to_format)
- : pimpl_(new Impl(from_file, to_file_base, from_format, to_format))
+ : pimpl_(new Impl(doc_fname, from_file, to_file_base, from_format, to_format))
{}
@@ -113,17 +117,20 @@ FileName const & Converter::convertedFile() const
/** Build the conversion script.
* The script is output to the stream \p script.
*/
-static void build_script(string const & from_file, string const & to_file_base,
+static void build_script(string const & doc_fname,
+ string const & from_file, string const & to_file_base,
string const & from_format, string const & to_format,
ostream & script);
-Converter::Impl::Impl(FileName const & from_file, string const & to_file_base,
+Converter::Impl::Impl(FileName const & doc_fname,
+ FileName const & from_file, string const & to_file_base,
string const & from_format, string const & to_format)
- : valid_process_(false), finished_(false)
+ : doc_fname_(doc_fname), valid_process_(false), finished_(false)
{
LYXERR(Debug::GRAPHICS, "Converter c-tor:\n"
- << "\tfrom_file: " << from_file
+ << "doc_fname: " << doc_fname
+ << "\n\tfrom_file: " << from_file
<< "\n\tto_file_base: " << to_file_base
<< "\n\tfrom_format: " << from_format
<< "\n\tto_format: " << to_format);
@@ -135,7 +142,7 @@ Converter::Impl::Impl(FileName const & from_file, string const & to_file_base,
// The conversion commands are stored in a stringstream
ostringstream script;
- build_script(from_file.toFilesystemEncoding(),
+ build_script(doc_fname_.absFileName(), from_file.toFilesystemEncoding(),
to_file_.toFilesystemEncoding(),
from_format, to_format, script);
LYXERR(Debug::GRAPHICS, "\tConversion script:"
@@ -264,7 +271,8 @@ static string const strip_digit(string const & format)
}
-static void build_script(string const & from_file,
+static void build_script(string const & doc_fname,
+ string const & from_file,
string const & to_file,
string const & from_format,
string const & to_format,
@@ -374,10 +382,19 @@ static void build_script(string const & from_file,
}
if (conv.need_auth()) {
+ std::set<std::string> & auth_files = theConverters().authFiles();
static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
- docstring const & question = bformat(from_utf8(securityWarning), from_utf8(conv.command()));
- int choice = frontend::Alert::prompt(
- from_utf8("Need user authorization to launch external converter"), question, 0, 0, from_utf8("&No"), from_utf8("&Yes"));
+ int choice;
+ if (auth_files.find(doc_fname) == auth_files.end()) {
+ docstring const & question = bformat(from_utf8(securityWarning), from_utf8(conv.command()));
+ choice = frontend::Alert::prompt(
+ from_utf8("Launch of external converter needs user authorization"), question,
+ 0, 0, from_utf8("&No"), from_utf8("&Yes"), from_utf8("Yes, &and do not ask again for document"));
+ if (choice == 2)
+ auth_files.insert(doc_fname);
+ } else {
+ choice = 1;
+ }
if (choice == 0)
return;
}
diff --git a/src/graphics/GraphicsConverter.h b/src/graphics/GraphicsConverter.h
index 2bd00037..d3d0b815 100644
--- a/src/graphics/GraphicsConverter.h
+++ b/src/graphics/GraphicsConverter.h
@@ -34,7 +34,8 @@ public:
/** One Converter per conversion ensures that the (hidden) signal
* is always connected to the expected slot.
*/
- Converter(support::FileName const & from_file, std::string const & to_file_base,
+ Converter(support::FileName const & doc_fname,
+ support::FileName const & from_file, std::string const & to_file_base,
std::string const & from_format, std::string const & to_format);
/// Needed for the pimpl
diff --git a/src/graphics/GraphicsLoader.cpp b/src/graphics/GraphicsLoader.cpp
index 36a6c06d..987a9731 100644
--- a/src/graphics/GraphicsLoader.cpp
+++ b/src/graphics/GraphicsLoader.cpp
@@ -18,6 +18,7 @@
#include "GraphicsCache.h"
#include "support/debug.h"
+#include "support/lassert.h"
#include "support/Timeout.h"
#include "support/bind.h"
@@ -30,6 +31,7 @@ using namespace std;
using namespace lyx::support;
namespace lyx {
+
namespace graphics {
@@ -162,9 +164,10 @@ void LoaderQueue::touch(Cache::ItemPtr const & item)
typedef std::shared_ptr<Image> ImagePtr;
class Loader::Impl : public boost::signals2::trackable {
+ friend class Loader;
public:
///
- Impl();
+ Impl(FileName const & doc_file);
///
~Impl();
///
@@ -178,6 +181,8 @@ public:
///
Params const & params() const { return params_; }
+ ///
+ FileName doc_file_;
/// The loading status of the image.
ImageStatus status_;
/** Must store a copy of the cached item to ensure that it is not
@@ -211,27 +216,35 @@ private:
};
-Loader::Loader()
- : pimpl_(new Impl)
+Loader::Loader(FileName const & doc_file)
+ : pimpl_(new Impl(doc_file))
{}
-Loader::Loader(FileName const & file, bool display)
- : pimpl_(new Impl)
+Loader::Loader(FileName const & doc_file, FileName const & file, bool display)
+ : pimpl_(new Impl(doc_file))
{
reset(file, display);
}
-Loader::Loader(FileName const & file, Params const & params)
- : pimpl_(new Impl)
+Loader::Loader(FileName const & doc_file, FileName const & file, Params const & params)
+ : pimpl_(new Impl(doc_file))
{
reset(file, params);
}
+Loader::Loader(FileName const & doc_file, Loader const & other)
+ : pimpl_(new Impl(doc_file))
+{
+ Params const & params = other.pimpl_->params();
+ reset(params.filename, params);
+}
+
+
Loader::Loader(Loader const & other)
- : pimpl_(new Impl)
+ : pimpl_(new Impl(other.pimpl_->doc_file_))
{
Params const & params = other.pimpl_->params();
reset(params.filename, params);
@@ -246,7 +259,10 @@ Loader::~Loader()
Loader & Loader::operator=(Loader const & other)
{
+ LASSERT(false, /**/);
if (this != &other) {
+ delete pimpl_;
+ pimpl_ = new Impl(other.pimpl_->doc_file_);
Params const & params = other.pimpl_->params();
reset(params.filename, params);
}
@@ -359,8 +375,8 @@ Image const * Loader::image() const
}
-Loader::Impl::Impl()
- : status_(WaitingToLoad)
+Loader::Impl::Impl(FileName const & doc_file)
+ : doc_file_(doc_file), status_(WaitingToLoad)
{
}
@@ -404,7 +420,7 @@ void Loader::Impl::resetFile(FileName const & file)
Cache & gc = Cache::get();
if (!gc.inCache(file))
- gc.add(file);
+ gc.add(file, doc_file_);
// We /must/ make a local copy of this.
cached_item_ = gc.item(file);
diff --git a/src/graphics/GraphicsLoader.h b/src/graphics/GraphicsLoader.h
index a90bd969..8b97114f 100644
--- a/src/graphics/GraphicsLoader.h
+++ b/src/graphics/GraphicsLoader.h
@@ -40,13 +40,15 @@ class Params;
class Loader {
public:
/// Must use the reset methods to make this instance usable.
- Loader();
+ Loader(support::FileName const & doc_file);
/// The image is not transformed, just displayed as-is.
- Loader(support::FileName const & file_with_path, bool display = true);
+ Loader(support::FileName const & doc_file, support::FileName const & file_with_path, bool display = true);
/// The image is transformed before display.
- Loader(support::FileName const & file_with_path, Params const &);
+ Loader(support::FileName const & doc_file, support::FileName const & file_with_path, Params const &);
///
- Loader(Loader const &);
+ Loader(support::FileName const & doc_file, Loader const &);
+ ///
+ Loader(Loader const & other);
/// Needed for the pimpl
~Loader();
@@ -108,7 +110,7 @@ private:
/// Use the Pimpl idiom to hide the internals.
class Impl;
/// The pointer never changes although *pimpl_'s contents may.
- Impl * const pimpl_;
+ Impl * pimpl_;
};
} // namespace graphics
diff --git a/src/graphics/PreviewImage.cpp b/src/graphics/PreviewImage.cpp
index 80e8e201..da0f1e21 100644
--- a/src/graphics/PreviewImage.cpp
+++ b/src/graphics/PreviewImage.cpp
@@ -99,11 +99,17 @@ Image const * PreviewImage::image() const
}
+PreviewLoader & PreviewImage::previewLoader() const
+{
+ return pimpl_->ploader_;
+}
+
+
PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l,
string const & s,
FileName const & bf,
double af)
- : parent_(p), ploader_(l), iloader_(bf),
+ : parent_(p), ploader_(l), iloader_(l.buffer().fileName(), bf),
snippet_(s), ascent_frac_(af)
{
iloader_.setDisplayPixelRatio(l.displayPixelRatio());
diff --git a/src/graphics/PreviewImage.h b/src/graphics/PreviewImage.h
index 04f1338e..6b5ac7e6 100644
--- a/src/graphics/PreviewImage.h
+++ b/src/graphics/PreviewImage.h
@@ -22,6 +22,7 @@ class Dimension;
namespace graphics {
+class Cache;
class PreviewLoader;
class Image;
@@ -49,6 +50,8 @@ public:
///
support::FileName const & filename() const;
+ PreviewLoader & previewLoader() const;
+
private:
/// Use the Pimpl idiom to hide the internals.
class Impl;
diff --git a/src/graphics/PreviewLoader.cpp b/src/graphics/PreviewLoader.cpp
index e1a47e84..df025e41 100644
--- a/src/graphics/PreviewLoader.cpp
+++ b/src/graphics/PreviewLoader.cpp
@@ -74,36 +74,6 @@ FileName const unique_tex_filename(FileName const & bufferpath)
}
-lyx::Converter const * setConverter(string const & from)
-{
- typedef vector<string> FmtList;
- typedef lyx::graphics::Cache GCache;
- FmtList const & loadableFormats = GCache::get().loadableFormats();
- FmtList::const_iterator it = loadableFormats.begin();
- FmtList::const_iterator const end = loadableFormats.end();
-
- for (; it != end; ++it) {
- string const to = *it;
- if (from == to)
- continue;
-
- lyx::Converter const * ptr = lyx::theConverters().getConverter(from, to);
- if (ptr)
- return ptr;
- }
-
- // Show the error only once. This is thread-safe.
- static nullptr_t no_conv = [&]{
- LYXERR0("PreviewLoader::startLoading()\n"
- << "No converter from \"" << from
- << "\" format has been defined.");
- return nullptr;
- } ();
-
- return no_conv;
-}
-
-
void setAscentFractions(vector<double> & ascent_fractions,
FileName const & metrics_file)
{
@@ -223,6 +193,8 @@ public:
Buffer const & buffer() const { return buffer_; }
+ lyx::Converter const * setConverter(string const & from);
+
private:
/// Called by the ForkedCall process that generated the bitmap files.
void finishedGenerating(pid_t, int);
@@ -433,6 +405,35 @@ PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b)
}
+lyx::Converter const * PreviewLoader::Impl::setConverter(string const & from)
+{
+ typedef vector<string> FmtList;
+ FmtList const & loadableFormats = graphics::Cache::get().loadableFormats();
+ FmtList::const_iterator it = loadableFormats.begin();
+ FmtList::const_iterator const end = loadableFormats.end();
+
+ for (; it != end; ++it) {
+ string const to = *it;
+ if (from == to)
+ continue;
+
+ lyx::Converter const * ptr = lyx::theConverters().getConverter(from, to);
+ if (ptr)
+ return ptr;
+ }
+
+ // Show the error only once. This is thread-safe.
+ static nullptr_t no_conv = [&]{
+ LYXERR0("PreviewLoader::startLoading()\n"
+ << "No converter from \"" << from
+ << "\" format has been defined.");
+ return nullptr;
+ } ();
+
+ return no_conv;
+}
+
+
PreviewLoader::Impl::~Impl()
{
delete delay_refresh_;
diff --git a/src/insets/RenderGraphic.cpp b/src/insets/RenderGraphic.cpp
index 9d9cf317..7ab14cb6 100644
--- a/src/insets/RenderGraphic.cpp
+++ b/src/insets/RenderGraphic.cpp
@@ -14,6 +14,7 @@
#include "insets/Inset.h"
+#include "Buffer.h"
#include "LyX.h"
#include "LyXRC.h"
#include "MetricsInfo.h"
@@ -35,6 +36,7 @@ namespace lyx {
RenderGraphic::RenderGraphic(Inset const * inset)
+ : loader_(inset->buffer().fileName())
{
loader_.connect(bind(&Inset::updateFrontend, inset));
}
--
2.9.3
>From 226e85f9e6a9fad37902a236885756979e78e7be Mon Sep 17 00:00:00 2001
From: Tommaso Cucinotta <tomm...@lyx.org>
Date: Sun, 13 Nov 2016 17:29:43 +0100
Subject: [PATCH 3/4] Added preference option for applying needauth option to
external converters.
Addressing #10481.
---
src/Converter.cpp | 3 ++-
src/LyXRC.cpp | 19 +++++++++++++++++
src/LyXRC.h | 5 +++++
src/frontends/qt4/GuiPrefs.cpp | 4 ++++
src/frontends/qt4/ui/PrefConvertersUi.ui | 35 ++++++++++++++++++++++++++++++++
src/graphics/GraphicsConverter.cpp | 3 ++-
6 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/src/Converter.cpp b/src/Converter.cpp
index 02631ca4..37aff9a7 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -21,6 +21,7 @@
#include "Format.h"
#include "Language.h"
#include "LaTeX.h"
+#include "LyXRC.h"
#include "Mover.h"
#include "frontends/alert.h"
@@ -404,7 +405,7 @@ bool Converters::convert(Buffer const * buffer,
"tmpfile.out"));
}
- if (conv.need_auth()) {
+ if (lyxrc.use_converter_needauth && conv.need_auth()) {
static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
int choice;
if (buffer) {
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index fe3b0423..433bfab8 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -189,6 +189,7 @@ LexerKeyword lyxrcTags[] = {
{ "\\thesaurusdir_path", LyXRC::RC_THESAURUSDIRPATH },
{ "\\ui_file", LyXRC::RC_UIFILE },
{ "\\use_converter_cache", LyXRC::RC_USE_CONVERTER_CACHE },
+ { "\\use_converter_needauth", LyXRC::RC_USE_CONVERTER_NEEDAUTH },
{ "\\use_lastfilepos", LyXRC::RC_USELASTFILEPOS },
{ "\\use_pixmap_cache", LyXRC::RC_USE_PIXMAP_CACHE },
{ "\\use_qimage", LyXRC::RC_USE_QIMAGE },
@@ -316,6 +317,7 @@ void LyXRC::setDefaults()
preview_hashed_labels = false;
preview_scale_factor = 1.0;
use_converter_cache = true;
+ use_converter_needauth = true;
use_system_colors = false;
use_tooltip = true;
use_pixmap_cache = false;
@@ -1112,6 +1114,9 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format)
case RC_USE_CONVERTER_CACHE:
lexrc >> use_converter_cache;
break;
+ case RC_USE_CONVERTER_NEEDAUTH:
+ lexrc >> use_converter_needauth;
+ break;
case RC_CONVERTER_CACHE_MAXAGE:
lexrc >> converter_cache_maxage;
break;
@@ -1593,6 +1598,15 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c
if (tag != RC_LAST)
break;
+ case RC_USE_CONVERTER_NEEDAUTH:
+ if (ignore_system_lyxrc ||
+ use_converter_needauth != system_lyxrc.use_converter_needauth) {
+ os << "\\use_converter_needauth "
+ << convert<string>(use_converter_needauth) << '\n';
+ }
+ if (tag != RC_LAST)
+ break;
+
case RC_CONVERTER_CACHE_MAXAGE:
if (ignore_system_lyxrc ||
converter_cache_maxage != system_lyxrc.converter_cache_maxage) {
@@ -2833,6 +2847,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
case LyXRC::RC_USER_EMAIL:
case LyXRC::RC_USER_NAME:
case LyXRC::RC_USE_CONVERTER_CACHE:
+ case LyXRC::RC_USE_CONVERTER_NEEDAUTH:
case LyXRC::RC_USE_SYSTEM_COLORS:
case LyXRC::RC_USE_TOOLTIP:
case LyXRC::RC_USE_PIXMAP_CACHE:
@@ -2925,6 +2940,10 @@ string const LyXRC::getDescription(LyXRCTags tag)
case RC_CONVERTER:
break;
+ case RC_CONVERTER_NEEDAUTH:
+ str = _("Ask user before calling external converters with 'needauth' option to prevent undesired effects.");
+ break;
+
case RC_COPIER:
break;
diff --git a/src/LyXRC.h b/src/LyXRC.h
index 7b50ce0a..b72e556e 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -167,6 +167,7 @@ public:
RC_USER_EMAIL,
RC_USER_NAME,
RC_USE_CONVERTER_CACHE,
+ RC_USE_CONVERTER_NEEDAUTH,
RC_USE_SYSTEM_COLORS,
RC_USE_TOOLTIP,
RC_USE_PIXMAP_CACHE,
@@ -443,6 +444,10 @@ public:
std::string texinputs_prefix;
/// Use the cache for file converters?
bool use_converter_cache;
+ /// Ask user before calling external converters with 'needauth' option
+ bool use_converter_needauth;
+ /// Apply hardening when calling external converters
+ bool use_converter_wrappers;
/// The maximum age of cache files in seconds
unsigned int converter_cache_maxage;
/// Sort layouts alphabetically
diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp
index dd59dbfe..2eacb59c 100644
--- a/src/frontends/qt4/GuiPrefs.cpp
+++ b/src/frontends/qt4/GuiPrefs.cpp
@@ -1610,6 +1610,8 @@ PrefConverters::PrefConverters(GuiPreferences * form)
this, SIGNAL(changed()));
connect(maxAgeLE, SIGNAL(textEdited(QString)),
this, SIGNAL(changed()));
+ connect(needauthCB, SIGNAL(toggled(bool)),
+ this, SIGNAL(changed()));
converterED->setValidator(new NoNewLineValidator(converterED));
converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
@@ -1621,6 +1623,7 @@ PrefConverters::PrefConverters(GuiPreferences * form)
void PrefConverters::applyRC(LyXRC & rc) const
{
rc.use_converter_cache = cacheCB->isChecked();
+ rc.use_converter_needauth = needauthCB;
rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
}
@@ -1628,6 +1631,7 @@ void PrefConverters::applyRC(LyXRC & rc) const
void PrefConverters::updateRC(LyXRC const & rc)
{
cacheCB->setChecked(rc.use_converter_cache);
+ needauthCB->setChecked(rc.use_converter_needauth);
QString max_age;
doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
updateGui();
diff --git a/src/frontends/qt4/ui/PrefConvertersUi.ui b/src/frontends/qt4/ui/PrefConvertersUi.ui
index 3fe6b9b8..1945246d 100644
--- a/src/frontends/qt4/ui/PrefConvertersUi.ui
+++ b/src/frontends/qt4/ui/PrefConvertersUi.ui
@@ -304,6 +304,41 @@
</layout>
</widget>
</item>
+ <item row="2" column="0" >
+ <widget class="QGroupBox" name="securityGB" >
+ <property name="title" >
+ <string>Security</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="needauthCB" >
+ <property name="text" >
+ <string>Use need&auth option</string>
+ </property>
+ <property name="toolTip">
+ <string>When enabled, ask user before launching any external converter with the 'needauth' option.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
<tabstops>
diff --git a/src/graphics/GraphicsConverter.cpp b/src/graphics/GraphicsConverter.cpp
index e12f6367..274efff8 100644
--- a/src/graphics/GraphicsConverter.cpp
+++ b/src/graphics/GraphicsConverter.cpp
@@ -15,6 +15,7 @@
#include "Buffer.h"
#include "Converter.h"
#include "Format.h"
+#include "LyXRC.h"
#include "frontends/alert.h"
#include "support/lassert.h"
@@ -381,7 +382,7 @@ static void build_script(string const & doc_fname,
outfile = tempfile.name().toFilesystemEncoding();
}
- if (conv.need_auth()) {
+ if (lyxrc.use_converter_needauth && conv.need_auth()) {
std::set<std::string> & auth_files = theConverters().authFiles();
static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
int choice;
--
2.9.3
>From c6e190adb5a82f711a39a38b7d8e80af01f23617 Mon Sep 17 00:00:00 2001
From: Tommaso Cucinotta <tomm...@lyx.org>
Date: Sun, 20 Nov 2016 19:46:10 +0100
Subject: [PATCH 4/4] Converter::auth_files code style fix, debugging and
bugfix.
---
src/Converter.cpp | 11 ++++++++---
src/Converter.h | 4 ++--
src/LyXRC.cpp | 19 +++++++++++++++++++
src/LyXRC.h | 3 +++
src/frontends/qt4/GuiPrefs.cpp | 12 +++++++++++-
src/frontends/qt4/GuiPrefs.h | 1 +
src/frontends/qt4/ui/PrefConvertersUi.ui | 14 ++++++++++++--
src/graphics/GraphicsConverter.cpp | 5 +++++
8 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/src/Converter.cpp b/src/Converter.cpp
index 37aff9a7..c6ff5bf6 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -405,17 +405,22 @@ bool Converters::convert(Buffer const * buffer,
"tmpfile.out"));
}
+ if (lyxrc.use_converter_needauth_forbidden && conv.need_auth()) {
+ frontend::Alert::warning(_("Potentially harmful external converters disabled"), _("Requested operation needs use of a potentially harmful external converter program, which is forbidden by default.\nThese converters are tagged by the 'needauth' option. In order to unlock execution of these converters,\nplease, go to Preferences->File Handling->Converters and uncheck Security->Forbid needauth converters."), true);
+ return false;
+ }
if (lyxrc.use_converter_needauth && conv.need_auth()) {
static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
int choice;
if (buffer) {
- std::string const & fname = buffer->filePath();
- if (auth_files.find(fname) == auth_files.end()) {
+ std::string const & fname = buffer->absFileName();
+ LYXERR(Debug::FILES, "looking up: " << fname);
+ if (auth_files_.find(fname) == auth_files_.end()) {
choice = frontend::Alert::prompt(
_("Launch of external converter needs user authorization"), bformat(_(securityWarning), from_utf8(conv.command())),
0, 0, _("&No"), _("&Yes"), _("Yes, &and do not ask again for document"));
if (choice == 2)
- auth_files.insert(fname);
+ auth_files_.insert(fname);
} else {
choice = 1;
}
diff --git a/src/Converter.h b/src/Converter.h
index 34d8db70..ef907461 100644
--- a/src/Converter.h
+++ b/src/Converter.h
@@ -187,7 +187,7 @@ public:
///
void buildGraph();
///
- std::set<std::string> & authFiles() { return auth_files; }
+ std::set<std::string> & authFiles() { return auth_files_; }
private:
///
@@ -219,7 +219,7 @@ private:
///
Graph G_;
/// set of files authorized for external conversion
- std::set<std::string> auth_files;
+ std::set<std::string> auth_files_;
};
/// The global instance.
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index 433bfab8..6f366a1a 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -189,6 +189,7 @@ LexerKeyword lyxrcTags[] = {
{ "\\thesaurusdir_path", LyXRC::RC_THESAURUSDIRPATH },
{ "\\ui_file", LyXRC::RC_UIFILE },
{ "\\use_converter_cache", LyXRC::RC_USE_CONVERTER_CACHE },
+ { "\\use_converter_needauth_forbidden", LyXRC::RC_USE_CONVERTER_NEEDAUTH_FORBIDDEN },
{ "\\use_converter_needauth", LyXRC::RC_USE_CONVERTER_NEEDAUTH },
{ "\\use_lastfilepos", LyXRC::RC_USELASTFILEPOS },
{ "\\use_pixmap_cache", LyXRC::RC_USE_PIXMAP_CACHE },
@@ -317,6 +318,7 @@ void LyXRC::setDefaults()
preview_hashed_labels = false;
preview_scale_factor = 1.0;
use_converter_cache = true;
+ use_converter_needauth_forbidden = true;
use_converter_needauth = true;
use_system_colors = false;
use_tooltip = true;
@@ -1114,6 +1116,9 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format)
case RC_USE_CONVERTER_CACHE:
lexrc >> use_converter_cache;
break;
+ case RC_USE_CONVERTER_NEEDAUTH_FORBIDDEN:
+ lexrc >> use_converter_needauth_forbidden;
+ break;
case RC_USE_CONVERTER_NEEDAUTH:
lexrc >> use_converter_needauth;
break;
@@ -1598,6 +1603,15 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c
if (tag != RC_LAST)
break;
+ case RC_USE_CONVERTER_NEEDAUTH_FORBIDDEN:
+ if (ignore_system_lyxrc ||
+ use_converter_needauth_forbidden != system_lyxrc.use_converter_needauth_forbidden) {
+ os << "\\use_converter_needauth_forbidden "
+ << convert<string>(use_converter_needauth_forbidden) << '\n';
+ }
+ if (tag != RC_LAST)
+ break;
+
case RC_USE_CONVERTER_NEEDAUTH:
if (ignore_system_lyxrc ||
use_converter_needauth != system_lyxrc.use_converter_needauth) {
@@ -2847,6 +2861,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
case LyXRC::RC_USER_EMAIL:
case LyXRC::RC_USER_NAME:
case LyXRC::RC_USE_CONVERTER_CACHE:
+ case LyXRC::RC_USE_CONVERTER_NEEDAUTH_FORBIDDEN:
case LyXRC::RC_USE_CONVERTER_NEEDAUTH:
case LyXRC::RC_USE_SYSTEM_COLORS:
case LyXRC::RC_USE_TOOLTIP:
@@ -2940,6 +2955,10 @@ string const LyXRC::getDescription(LyXRCTags tag)
case RC_CONVERTER:
break;
+ case RC_CONVERTER_NEEDAUTH_FORBIDDEN:
+ str = _("Forbid use of external converters with 'needauth' option to prevent undesired effects.");
+ break;
+
case RC_CONVERTER_NEEDAUTH:
str = _("Ask user before calling external converters with 'needauth' option to prevent undesired effects.");
break;
diff --git a/src/LyXRC.h b/src/LyXRC.h
index b72e556e..010e9571 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -167,6 +167,7 @@ public:
RC_USER_EMAIL,
RC_USER_NAME,
RC_USE_CONVERTER_CACHE,
+ RC_USE_CONVERTER_NEEDAUTH_FORBIDDEN,
RC_USE_CONVERTER_NEEDAUTH,
RC_USE_SYSTEM_COLORS,
RC_USE_TOOLTIP,
@@ -444,6 +445,8 @@ public:
std::string texinputs_prefix;
/// Use the cache for file converters?
bool use_converter_cache;
+ /// Forbid use of external converters with 'needauth' option
+ bool use_converter_needauth_forbidden;
/// Ask user before calling external converters with 'needauth' option
bool use_converter_needauth;
/// Apply hardening when calling external converters
diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp
index 2eacb59c..ee43b4fd 100644
--- a/src/frontends/qt4/GuiPrefs.cpp
+++ b/src/frontends/qt4/GuiPrefs.cpp
@@ -1610,6 +1610,8 @@ PrefConverters::PrefConverters(GuiPreferences * form)
this, SIGNAL(changed()));
connect(maxAgeLE, SIGNAL(textEdited(QString)),
this, SIGNAL(changed()));
+ connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
+ this, SIGNAL(changed()));
connect(needauthCB, SIGNAL(toggled(bool)),
this, SIGNAL(changed()));
@@ -1623,7 +1625,8 @@ PrefConverters::PrefConverters(GuiPreferences * form)
void PrefConverters::applyRC(LyXRC & rc) const
{
rc.use_converter_cache = cacheCB->isChecked();
- rc.use_converter_needauth = needauthCB;
+ rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
+ rc.use_converter_needauth = needauthCB->isChecked();
rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
}
@@ -1631,6 +1634,7 @@ void PrefConverters::applyRC(LyXRC & rc) const
void PrefConverters::updateRC(LyXRC const & rc)
{
cacheCB->setChecked(rc.use_converter_cache);
+ needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
needauthCB->setChecked(rc.use_converter_needauth);
QString max_age;
doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
@@ -1792,6 +1796,12 @@ void PrefConverters::on_cacheCB_stateChanged(int state)
}
+void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
+{
+ needauthCB->setEnabled(!checked);
+}
+
+
/////////////////////////////////////////////////////////////////////
//
// FormatValidator
diff --git a/src/frontends/qt4/GuiPrefs.h b/src/frontends/qt4/GuiPrefs.h
index 1b37b323..612ffe6b 100644
--- a/src/frontends/qt4/GuiPrefs.h
+++ b/src/frontends/qt4/GuiPrefs.h
@@ -334,6 +334,7 @@ private Q_SLOTS:
void removeConverter();
void changeConverter();
void on_cacheCB_stateChanged(int state);
+ void on_needauthForbiddenCB_toggled(bool);
private:
void updateButtons();
diff --git a/src/frontends/qt4/ui/PrefConvertersUi.ui b/src/frontends/qt4/ui/PrefConvertersUi.ui
index 1945246d..7e4a1b32 100644
--- a/src/frontends/qt4/ui/PrefConvertersUi.ui
+++ b/src/frontends/qt4/ui/PrefConvertersUi.ui
@@ -324,7 +324,17 @@
<property name="spacing" >
<number>6</number>
</property>
- <item>
+ <item>
+ <widget class="QCheckBox" name="needauthForbiddenCB" >
+ <property name="text" >
+ <string>&Forbid use of needauth converters</string>
+ </property>
+ <property name="toolTip">
+ <string>When enabled, use of converters with the 'needauth' option is forbidden.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="needauthCB" >
<property name="text" >
<string>Use need&auth option</string>
@@ -333,7 +343,7 @@
<string>When enabled, ask user before launching any external converter with the 'needauth' option.</string>
</property>
</widget>
- </item>
+ </item>
</layout>
</item>
</layout>
diff --git a/src/graphics/GraphicsConverter.cpp b/src/graphics/GraphicsConverter.cpp
index 274efff8..b1c2e8a8 100644
--- a/src/graphics/GraphicsConverter.cpp
+++ b/src/graphics/GraphicsConverter.cpp
@@ -382,7 +382,12 @@ static void build_script(string const & doc_fname,
outfile = tempfile.name().toFilesystemEncoding();
}
+ if (lyxrc.use_converter_needauth_forbidden && conv.need_auth()) {
+ frontend::Alert::warning(from_utf8("Potentially harmful external converters disabled"), from_utf8("Requested operation needs use of a potentially harmful external converter program, which is forbidden by default.\nThese converters are tagged by the 'needauth' option. In order to unlock execution of these converters,\nplease, go to Preferences->File Handling->Converters and uncheck Security->Forbid needauth converters."), true);
+ return;
+ }
if (lyxrc.use_converter_needauth && conv.need_auth()) {
+ LYXERR(Debug::FILES, "looking up: " << doc_fname);
std::set<std::string> & auth_files = theConverters().authFiles();
static const char securityWarning[] = "LyX is about to run converter '%1$s' which is launching an external program that normally acts as a picture/format converter. However, this external program is known to be able to execute arbitrary actions on the system, including dangerous ones such as deleting files, if instructed to do so by a maliciously crafted .lyx document.\n Would you like to proceed?\nAnswer Yes only if you trust the source/sender of the .lyx document!";
int choice;
--
2.9.3