]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/util.cxx
Interim windows build fix
[flightgear.git] / src / Main / util.cxx
index 40d3244d6dfeb3bfa24176c11a01a4739c183af0..6bc4ddb50f36093591778d1ee750c91bb7a56167 100644 (file)
@@ -72,83 +72,69 @@ fgGetLowPass (double current, double target, double timeratio)
     return current;
 }
 
-// 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;
- }
-
 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();
-    std::string fg_root = fgNormalizePath(globals->get_fg_root());
-    std::string fg_home = fgNormalizePath(globals->get_fg_home());
-    read_allowed_paths.push_back(fg_root + "/*");
-    read_allowed_paths.push_back(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(fgNormalizePath(*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(fg_home + "/*.sav");
-    write_allowed_paths.push_back(fg_home + "/*.log");
-    write_allowed_paths.push_back(fg_home + "/cache/*");
-    write_allowed_paths.push_back(fg_home + "/Export/*");
-    write_allowed_paths.push_back(fg_home + "/state/*.xml");
-    write_allowed_paths.push_back(fg_home + "/aircraft-data/*.xml");
-    write_allowed_paths.push_back(fg_home + "/Wildfire/*.xml");
-    write_allowed_paths.push_back(fg_home + "/runtime-jetways/*.xml");
-    write_allowed_paths.push_back(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() ||
@@ -156,7 +142,6 @@ void fgInitAllowedPaths()
         !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(globals->get_fg_home() + "/./TerraSync/../Export\\yes..gg",true).empty() ||
         fgValidatePath(globals->get_fg_home() + "/aircraft-data/yes..xml",true).empty() ||
         fgValidatePath(globals->get_fg_root() + "/.\\yes.bmp",false).empty()) {
             flightgear::fatalMessageBox("Nasal initialization error",
@@ -166,9 +151,18 @@ void fgInitAllowedPaths()
     }
 }
 
-// Check whether Nasal is allowed to access a path (assumed already normalized)
-static std::string fgValidatePath_internal (const std::string& normed_path, bool write)
+/**
+ * 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;
     
@@ -196,34 +190,6 @@ static std::string fgValidatePath_internal (const std::string& normed_path, bool
     // no match found
     return "";
 }
-// Check whether Nasal is allowed to access a path
-// Warning: because this always (not just on Windows) converts \ to /,
-// if passing a std::string, use the returned path not the original one
-// (This warning does not apply to the SGPath variant, as these are
-// so converted on creation.)
-std::string fgValidatePath (const std::string& path, bool write)
-{
-    // Normalize the path (prevents ../../.. trickery)
-    // method 1 allows following symlinks to anywhere
-    // (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=780867);
-    // method 2 doesn't, and is intended to eventually replace it
-    std::string normed_path1 = fgNormalizePath(path);
-    SGPath path2 = SGPath(path);
-    std::string normed_path2;
-    if (path2.exists()) {
-        normed_path2 = path2.realpath();
-    } else { // realpath can't check non-existent files
-        normed_path2 = SGPath(path2.dir()).realpath()
-            + "/" + path2.file();
-    }
-
-    // Check
-    if (fgValidatePath_internal(normed_path1, write).empty() ||
-        fgValidatePath_internal(normed_path2, write).empty()) {
-        return "";
-    }
-    return normed_path1;
-}
 std::string fgValidatePath(const SGPath& path, bool write) { return fgValidatePath(path.str(),write); }
 // end of util.cxx