- move fixpath() from "string" to "io" module
- first stab at Nasal security model: allow writing files only to authorized dirs. (Most of the debug messages will be removed later.)
This commit is contained in:
parent
219f8d9a3a
commit
7d9bd68742
2 changed files with 66 additions and 31 deletions
66
Nasal/io.nas
66
Nasal/io.nas
|
@ -113,4 +113,70 @@ var writexml = func(path, node, indent = "\t", prefix = "___") {
|
|||
die("writexml(): tree has more than one root node");
|
||||
}
|
||||
|
||||
# Removes superfluous slashes, empty and "." elements, expands
|
||||
# all ".." elements, and turns all backslashes into slashes.
|
||||
# The result will start with a slash if it started with a slash
|
||||
# or backslash, it will end without slash. Should be applied on
|
||||
# absolute property or file paths, otherwise ".." elements might
|
||||
# be resolved wrongly.
|
||||
#
|
||||
var fixpath = func(path) {
|
||||
var d = "";
|
||||
for(var i = 0; i < size(path); i += 1)
|
||||
d ~= path[i] == `\\` ? "/" : chr(path[i]);
|
||||
|
||||
var prefix = d[0] == `/` ? "/" : "";
|
||||
var stack = [];
|
||||
foreach(var e; split("/", d)) {
|
||||
if(e == "." or e == "")
|
||||
continue;
|
||||
elsif(e == "..")
|
||||
pop(stack);
|
||||
else
|
||||
append(stack, e);
|
||||
}
|
||||
if(!size(stack))
|
||||
return "/";
|
||||
path = stack[0];
|
||||
foreach(var s; subvec(stack, 1))
|
||||
path ~= "/" ~ s;
|
||||
return prefix ~ path;
|
||||
}
|
||||
|
||||
# Redefine io.open() such that files can only be written under authorized directories.
|
||||
#
|
||||
setlistener("/sim/signals/nasal-dir-initialized", func {
|
||||
var writable_dirs = [
|
||||
# "*", # any
|
||||
# fixpath(getprop("/sim/fg-root")) ~ "/Scenery/",
|
||||
fixpath(getprop("/sim/fg-home")) ~ "/",
|
||||
"/tmp/", "/var/tmp/", "/var/log/",
|
||||
"[A-Za-z]:TMP/", "[A-Za-z]:TEMP/",
|
||||
"[A-Za-z]:/TMP/", "[A-Za-z]:/TEMP/",
|
||||
];
|
||||
|
||||
var _open = open;
|
||||
open = func(path, mode = "rb") {
|
||||
var c = caller(1);
|
||||
print(debug._path("SECURITY: io.open(\"" ~ path ~ "\", \"" ~ mode ~ "\")\n in file "
|
||||
~ c[2] ~ ", line " ~ c[3]));
|
||||
|
||||
if(mode == "r") {
|
||||
print(debug._nil("SECURITY: allow reading of file '" ~ path ~ "'"));
|
||||
return _open(path, mode);
|
||||
}
|
||||
|
||||
var fpath = fixpath(path);
|
||||
if(fpath != path) print(debug._error("SECURITY: fix path '" ~ path ~ "' -> '" ~ fpath ~ "'"));
|
||||
foreach(var p; writable_dirs) {
|
||||
print("SECURITY: check for path '" ~ p ~ "'");
|
||||
if(string.match(fpath, p ~ '*')) {
|
||||
print(debug._nil("SECURITY: allow path '" ~ p ~ "'"));
|
||||
return _open(fpath, mode);
|
||||
}
|
||||
}
|
||||
|
||||
die("io.open(): security: writing to file '" ~ path ~ "' denied\n ");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -155,34 +155,3 @@ var match = func(str, patt) {
|
|||
}
|
||||
|
||||
|
||||
##
|
||||
# Removes superfluous slashes, empty and "." elements, expands
|
||||
# all ".." elements, and turns all backslashes into slashes.
|
||||
# The result will start with a slash if it started with a slash
|
||||
# or backslash, it will end without slash. Should be applied on
|
||||
# absolute property or file paths, otherwise ".." elements might
|
||||
# be resolved wrongly.
|
||||
#
|
||||
var fixpath = func(path) {
|
||||
var d = "";
|
||||
for (var i = 0; i < size(path); i += 1)
|
||||
d ~= path[i] == `\\` ? "/" : chr(path[i]);
|
||||
|
||||
var prefix = d[0] == `/` ? "/" : "";
|
||||
var stack = [];
|
||||
foreach (var e; split("/", d)) {
|
||||
if (e == "." or e == "")
|
||||
continue;
|
||||
elsif (e == "..")
|
||||
pop(stack);
|
||||
else
|
||||
append(stack, e);
|
||||
}
|
||||
if (!size(stack))
|
||||
return "/";
|
||||
path = stack[0];
|
||||
foreach (var s; subvec(stack, 1))
|
||||
path ~= "/" ~ s;
|
||||
return prefix ~ path;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue