]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/util.cxx
Interim windows build fix
[flightgear.git] / src / Main / util.cxx
index 15f7158d506d366913f08c8a55d517ef742d4940..6bc4ddb50f36093591778d1ee750c91bb7a56167 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <simgear/compiler.h>
 
-#include <math.h>
+#include <cmath>
 
 #include <cstdlib>
 
@@ -75,57 +75,75 @@ fgGetLowPass (double current, double target, double timeratio)
 static string_list read_allowed_paths;
 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
+/**
+ * Allowed paths here are absolute, and may contain _one_ *,
+ * which matches any string
+ */
 void fgInitAllowedPaths()
 {
+    if(SGPath("ygjmyfvhhnvdoesnotexist").realpath() == "ygjmyfvhhnvdoesnotexist"){
+        // Forbid using this version of fgValidatePath() with older
+        // (not normalizing non-existent files) versions of realpath(),
+        // as that would be a security hole
+        flightgear::fatalMessageBox("Nasal initialization error",
+                                    "Version mismatch - please update simgear",
+                                    "");
+        exit(-1);
+    }
     read_allowed_paths.clear();
     write_allowed_paths.clear();
-    read_allowed_paths.push_back(globals->get_fg_root() + "/*");
-    read_allowed_paths.push_back(globals->get_fg_home() + "/*");
+    std::string fg_root = SGPath(globals->get_fg_root()).realpath();
+    std::string fg_home = SGPath(globals->get_fg_home()).realpath();
+#if defined(_MSC_VER) /*for MS compilers */ || defined(_WIN32) /*needed for non MS windows compilers like MingW*/
+     std::string sep = "\\";
+#else
+     std::string sep = "/";
+#endif
+    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 )
-    {
-        read_allowed_paths.push_back(*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 = read_allowed_paths.begin();
-                                     it != read_allowed_paths.end();
-                                   ++it )
-    { // if we get the initialization order wrong, better to have an
+    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->compare("/*"))){
+        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 + "*");
     }
-    write_allowed_paths.push_back("/tmp/*.xml");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/*.sav");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/*.log");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/cache/*");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/Export/*");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/state/*.xml");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/aircraft-data/*.xml");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/Wildfire/*.xml");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/runtime-jetways/*.xml");
-    write_allowed_paths.push_back(globals->get_fg_home() + "/Input/Joysticks/*.xml");
+
+    write_allowed_paths.push_back(fg_home + sep + "*.sav");
+    write_allowed_paths.push_back(fg_home + sep + "*.log");
+    write_allowed_paths.push_back(fg_home + sep + "cache" + sep + "*");
+    write_allowed_paths.push_back(fg_home + sep + "Export" + sep + "*");
+    write_allowed_paths.push_back(fg_home + sep + "state" + sep + "*.xml");
+    write_allowed_paths.push_back(fg_home + sep + "aircraft-data" + sep + "*.xml");
+    write_allowed_paths.push_back(fg_home + sep + "Wildfire" + sep + "*.xml");
+    write_allowed_paths.push_back(fg_home + sep + "runtime-jetways" + sep + "*.xml");
+    write_allowed_paths.push_back(fg_home + sep + "Input" + sep + "Joysticks" + sep + "*.xml");
     
     // Check that it works
     if(!fgValidatePath(globals->get_fg_home() + "/../no.log",true).empty() ||
-        !fgValidatePath(globals->get_fg_home() + "/no.lot",true).empty() ||
+        !fgValidatePath(globals->get_fg_home() + "/no.logt",true).empty() ||
         !fgValidatePath(globals->get_fg_home() + "/nolog",true).empty() ||
         !fgValidatePath(globals->get_fg_home() + "no.log",true).empty() ||
-        !fgValidatePath("..\\" + globals->get_fg_home() + "/no.log",false).empty() ||
-        !fgValidatePath(std::string("/tmp/no.xml"),false).empty() ||
-        fgValidatePath(globals->get_fg_home() + "/./ff/../Export\\yes..gg",true).empty() ||
+        !fgValidatePath(globals->get_fg_home() + "\\..\\no.log",false).empty() ||
         fgValidatePath(globals->get_fg_home() + "/aircraft-data/yes..xml",true).empty() ||
-        fgValidatePath(globals->get_fg_root() + "/./\\yes.bmp",false).empty()) {
+        fgValidatePath(globals->get_fg_root() + "/.\\yes.bmp",false).empty()) {
             flightgear::fatalMessageBox("Nasal initialization error",
                                     "fgInitAllowedPaths() does not work",
                                     "");
@@ -133,49 +151,21 @@ void fgInitAllowedPaths()
     }
 }
 
-// Normalize a path
-// Unlike SGPath::realpath, does not require that the file already exists,
-// but does require that it be below the starting point
-static std::string fgNormalizePath (const std::string& path)
-{
-    string_list path_parts;
-    char c;
-    std::string normed_path = "", this_part = "";
-    
-    for (int pos = 0; ; pos++) {
-        c = path[pos];
-        if (c == '\\') { c = '/'; }
-        if ((c == '/') || (c == 0)) {
-            if ((this_part == "/..") || (this_part == "..")) {
-                if (path_parts.empty()) { return ""; }
-                path_parts.pop_back();
-            } else if ((this_part != "/.") && (this_part != "/")) {
-                path_parts.push_back(this_part);
-            }
-            this_part = "";
-        }
-        if (c == 0) { break; }
-        this_part = this_part + c;
-    }
-    for( string_list::const_iterator it = path_parts.begin();
-                                     it != path_parts.end();
-                                   ++it )
-    {
-        normed_path.append(*it);
-    }
-    return normed_path;
- }
-
-
-// Check whether Nasal is allowed to access a path
+/**
+ * Check whether Nasal is allowed to access a path
+ * Warning: because this always (not just on Windows) treats both \ and /
+ * as path separators, and accepts relative paths (check-to-use race if
+ * the current directory changes),
+ * always use the returned path not the original one
+ */
 std::string fgValidatePath (const std::string& path, bool write)
 {
+    // Normalize the path (prevents ../../.. or symlink trickery)
+    std::string normed_path = SGPath(path).realpath();
+    
     const string_list& allowed_paths(write ? write_allowed_paths : read_allowed_paths);
     size_t star_pos;
     
-    // Normalize the path (prevents ../../.. trickery)
-    std::string normed_path = fgNormalizePath(path);
-
     // Check against each allowed pattern
     for( string_list::const_iterator it = allowed_paths.begin();
                                      it != allowed_paths.end();