From: Rebecca N. Palmer Date: Sun, 22 Nov 2015 11:27:39 +0000 (+0000) Subject: fgValidatePath: allow Nasal to read user-set scenery directories X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=3e462f3056636ff1770ac5830cb917e5ac27aad7;p=flightgear.git fgValidatePath: allow Nasal to read user-set scenery directories (but not the Terrasync directory, as Nasal can change that) --- diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index f0ce2354e..4425aabb0 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -354,7 +354,7 @@ SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const return SGPath(); } -void FGGlobals::append_fg_scenery (const std::string &paths) +void FGGlobals::append_fg_scenery (const std::string &paths, bool secure) { SGPropertyNode* sim = fgGetNode("/sim", true); @@ -387,6 +387,9 @@ void FGGlobals::append_fg_scenery (const std::string &paths) // out, such that all three dirs are added. Unfortunately there's // no information as to why the change was made. fg_scenery.push_back(abspath.str()); + if (secure) { + secure_fg_scenery.push_back(abspath.str()); + } if (terrainDir.exists()) { fg_scenery.push_back(terrainDir.str()); @@ -414,6 +417,7 @@ void FGGlobals::append_fg_scenery (const std::string &paths) void FGGlobals::clear_fg_scenery() { fg_scenery.clear(); + secure_fg_scenery.clear(); } void FGGlobals::set_catalog_aircraft_path(const SGPath& path) diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index cf8680ac3..f5a3f20d5 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -107,6 +107,7 @@ private: // Roots of FlightGear scenery tree string_list fg_scenery; + string_list secure_fg_scenery; std::string browser; @@ -224,7 +225,16 @@ public: void set_fg_home (const std::string &home); inline const string_list &get_fg_scenery () const { return fg_scenery; } - void append_fg_scenery (const std::string &scenery); + inline const string_list &get_secure_fg_scenery () const { return secure_fg_scenery; } + /** + * Add a scenery directory + * + * secure = allow Nasal to read this directory; to avoid + * can-read-any-file security holes, do NOT set this on directories + * obtained from the property tree (e.g. /sim/terrasync/scenery-dir) + * or other Nasal-writable places + */ + void append_fg_scenery (const std::string &scenery, bool secure = false); void clear_fg_scenery(); diff --git a/src/Main/options.cxx b/src/Main/options.cxx index cd9fe75db..00f2352a1 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -851,7 +851,7 @@ fgOptRoc( const char *arg ) static int fgOptFgScenery( const char *arg ) { - globals->append_fg_scenery(arg); + globals->append_fg_scenery(arg, true); return FG_OPTIONS_OK; } @@ -2278,7 +2278,7 @@ OptionResult Options::processOptions() // now options are process, do supplemental fixup const char *envp = ::getenv( "FG_SCENERY" ); if (envp) { - globals->append_fg_scenery(envp); + globals->append_fg_scenery(envp, true); } // download dir fix-up diff --git a/src/Main/util.cxx b/src/Main/util.cxx index 65983ce04..6bc4ddb50 100644 --- a/src/Main/util.cxx +++ b/src/Main/util.cxx @@ -78,8 +78,6 @@ static string_list write_allowed_paths; /** * Allowed paths here are absolute, and may contain _one_ *, * which matches any string - * FG_SCENERY is deliberately not allowed, as it would make - * /sim/terrasync/scenery-dir a security hole */ void fgInitAllowedPaths() { @@ -104,16 +102,25 @@ void fgInitAllowedPaths() read_allowed_paths.push_back(fg_root + sep + "*"); read_allowed_paths.push_back(fg_home + sep + "*"); string_list const aircraft_paths = globals->get_aircraft_paths(); - for( string_list::const_iterator it = aircraft_paths.begin(); - it != aircraft_paths.end(); - ++it ) + string_list const scenery_paths = globals->get_secure_fg_scenery(); + // not plain fg_scenery, to avoid making + // /sim/terrasync/scenery-dir a security hole + + for( string_list::const_iterator it = aircraft_paths.begin();;++it ) { + if (it == aircraft_paths.end()) { + it = scenery_paths.begin(); + } + if (it == scenery_paths.end()) { + break; // here rather than in the loop condition because + // scenery_paths may be empty + } // if we get the initialization order wrong, better to have an // obvious error than a can-read-everything security hole... if (it->empty() || fg_root.empty() || fg_home.empty()){ flightgear::fatalMessageBox("Nasal initialization error", - "Empty string in FG_ROOT, FG_HOME or FG_AIRCRAFT", - "or fgInitAllowedPaths() called too early"); + "Empty string in FG_ROOT, FG_HOME, FG_AIRCRAFT or FG_SCENERY", + "or fgInitAllowedPaths() called too early"); exit(-1); } read_allowed_paths.push_back(SGPath(*it).realpath() + sep + "*");