From 76a13e689d5c55def97074a98fc9b0efc31df624 Mon Sep 17 00:00:00 2001 From: mfranz Date: Fri, 11 Jul 2008 16:36:54 +0000 Subject: [PATCH] use same path validation process for fgcommands "load", "save", "loadxml", ans "savexml" as is used for io.open(). This is still Nasal based for now. See $FG_ROOT/Nasal/io.nas. --- src/Main/fg_commands.cxx | 72 +++++++++++++++++++++++++++------------- src/Main/main.cxx | 2 ++ src/Main/util.cxx | 16 ++++++++- src/Main/util.hxx | 8 +++++ 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index caec3c0d1..b4b07ddce 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -320,16 +320,23 @@ do_resume (const SGPropertyNode * arg) static bool do_load (const SGPropertyNode * arg) { - const string &file = arg->getStringValue("file", "fgfs.sav"); - ifstream input(file.c_str()); - if (input.good() && fgLoadFlight(input)) { - input.close(); - SG_LOG(SG_INPUT, SG_INFO, "Restored flight from " << file); - return true; - } else { - SG_LOG(SG_INPUT, SG_WARN, "Cannot load flight from " << file); - return false; - } + const string &file = arg->getStringValue("file", "fgfs.sav"); + + if (!fgValidatePath(file.c_str(), false)) { + SG_LOG(SG_IO, SG_ALERT, "load: reading '" << file << "' denied " + "(unauthorized access)"); + return false; + } + + ifstream input(file.c_str()); + if (input.good() && fgLoadFlight(input)) { + input.close(); + SG_LOG(SG_INPUT, SG_INFO, "Restored flight from " << file); + return true; + } else { + SG_LOG(SG_INPUT, SG_WARN, "Cannot load flight from " << file); + return false; + } } @@ -342,18 +349,25 @@ do_load (const SGPropertyNode * arg) static bool do_save (const SGPropertyNode * arg) { - const string &file = arg->getStringValue("file", "fgfs.sav"); - bool write_all = arg->getBoolValue("write-all", false); - SG_LOG(SG_INPUT, SG_INFO, "Saving flight"); - ofstream output(file.c_str()); - if (output.good() && fgSaveFlight(output, write_all)) { - output.close(); - SG_LOG(SG_INPUT, SG_INFO, "Saved flight to " << file); - return true; - } else { - SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight to " << file); - return false; - } + const string &file = arg->getStringValue("file", "fgfs.sav"); + + if (!fgValidatePath(file.c_str(), false)) { + SG_LOG(SG_IO, SG_ALERT, "save: reading '" << file << "' denied " + "(unauthorized access)"); + return false; + } + + bool write_all = arg->getBoolValue("write-all", false); + SG_LOG(SG_INPUT, SG_INFO, "Saving flight"); + ofstream output(file.c_str()); + if (output.good() && fgSaveFlight(output, write_all)) { + output.close(); + SG_LOG(SG_INPUT, SG_INFO, "Saved flight to " << file); + return true; + } else { + SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight to " << file); + return false; + } } @@ -1336,6 +1350,12 @@ do_load_xml_to_proptree(const SGPropertyNode * arg) if (file.extension() != "xml") file.concat(".xml"); + if (!fgValidatePath(file.c_str(), false)) { + SG_LOG(SG_IO, SG_ALERT, "loadxml: reading '" << file.str() << "' denied " + "(unauthorized access)"); + return false; + } + SGPropertyNode *targetnode; if (arg->hasValue("targetnode")) targetnode = fgGetNode(arg->getStringValue("targetnode"), true); @@ -1349,7 +1369,7 @@ do_load_xml_to_proptree(const SGPropertyNode * arg) return false; } - return true; + return true; } @@ -1376,6 +1396,12 @@ do_save_xml_from_proptree(const SGPropertyNode * arg) if (file.extension() != "xml") file.concat(".xml"); + if (!fgValidatePath(file.c_str(), true)) { + SG_LOG(SG_IO, SG_ALERT, "savexml: writing to '" << file.str() << "' denied " + "(unauthorized access)"); + return false; + } + SGPropertyNode *sourcenode; if (arg->hasValue("sourcenode")) sourcenode = fgGetNode(arg->getStringValue("sourcenode"), true); diff --git a/src/Main/main.cxx b/src/Main/main.cxx index fd6d07818..146bd50fd 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -81,6 +81,7 @@ #include "renderer.hxx" #include "splash.hxx" #include "main.hxx" +#include "util.hxx" static double real_delta_time_sec = 0.0; @@ -984,6 +985,7 @@ bool fgMainInit( int argc, char **argv ) { string_list *col = new string_list; globals->set_channel_options_list( col ); + fgValidatePath("", false); // initialize static variables upper_case_property("/sim/presets/airport-id"); upper_case_property("/sim/presets/runway"); upper_case_property("/sim/tower/airport-id"); diff --git a/src/Main/util.cxx b/src/Main/util.cxx index b61985ca6..909cbad12 100644 --- a/src/Main/util.cxx +++ b/src/Main/util.cxx @@ -147,7 +147,7 @@ fgGetLowPass (double current, double target, double timeratio) string -fgUnescape(const char *s) +fgUnescape (const char *s) { string r; while (*s) { @@ -197,5 +197,19 @@ fgUnescape(const char *s) return r; } + +const char *fgValidatePath (const char *str, bool write) +{ + static SGPropertyNode_ptr r, w; + if (!r) { + r = fgGetNode("/sim/paths/validate/read", true); + w = fgGetNode("/sim/paths/validate/write", true); + } + SGPropertyNode *prop = write ? w : r; + prop->setStringValue(str); + const char *result = prop->getStringValue(); + return result[0] ? result : 0; +} + // end of util.cxx diff --git a/src/Main/util.hxx b/src/Main/util.hxx index bcd64658a..70067d3e3 100644 --- a/src/Main/util.hxx +++ b/src/Main/util.hxx @@ -83,4 +83,12 @@ extern double fgGetLowPass (double current, double target, double timeratio); extern std::string fgUnescape (const char *str); +/** + * Validation listener interface for io.nas, used by fgcommands. + * @param path Path to be validated + * @param write True for write operations and false for read operations. + * @return The validated path on success or 0 if access denied. + */ +extern const char *fgValidatePath (const char *path, bool write); + #endif // __UTIL_HXX -- 2.39.5