diff --git a/Nasal/io.nas b/Nasal/io.nas index 2ea7f840a..7fa7a0998 100644 --- a/Nasal/io.nas +++ b/Nasal/io.nas @@ -210,7 +210,7 @@ var writexml = func(path, node, indent = "\t", prefix = "___") { # Redefine io.open() such that files can only be opened under authorized directories. # _setlistener("/sim/signals/nasal-dir-initialized", func { - var thislistener = thisfunc(); + # read IO rules var root = string.fixpath(getprop("/sim/fg-root")); var home = string.fixpath(getprop("/sim/fg-home")); var config = "Nasal/IOrules"; @@ -264,10 +264,13 @@ _setlistener("/sim/signals/nasal-dir-initialized", func { print("io.open()/WRITE: ", debug.string(write_rules)); } - var fixpath = string.fixpath; # safe copies + # make safe, local copies + var setValue = props._setValue; + var getValue = props._getValue; + var fixpath = string.fixpath; var match = string.match; - var die = die; var caller = caller; + var die = die; var valid = func(path, rules) { var fpath = fixpath(path); @@ -277,7 +280,20 @@ _setlistener("/sim/signals/nasal-dir-initialized", func { return nil; } - var io_open = func(path, mode = "rb") { + # validation listeners for load[xml]/save[xml]/parsexml() (see utils.cxx:fgValidatePath) + var v = props.globals.getNode(var val = "/sim/paths/validate", 1); + _setlistener(val ~ "/read", var read_validator = func(n) { + setValue(n, [valid(getValue(n, []), read_rules) or ""]); + }); + _setlistener(val ~ "/write", var write_validator = func(n) { + setValue(n, [valid(getValue(n, []), write_rules) or ""]); + }); + v.remove(); # detach nodes to make them inaccessible for others + + + # wrap io.open() + var _open = io.open; + io.open = var io_open = func(path, mode = "rb") { var rules = write_rules; if(mode == "r" or mode == "rb" or mode == "br") rules = read_rules; @@ -287,21 +303,16 @@ _setlistener("/sim/signals/nasal-dir-initialized", func { die("io.open(): opening file '" ~ path ~ "' denied (unauthorized access)\n "); } - var _open = io.open; - io.open = io_open; + # wrap closure() to prevent tampering of security related functions + var thislistener = caller(0)[1]; var _closure = globals.closure; globals.closure = func(fn, level = 0) { - if(fn != thislistener and fn != caller(0)[1] and fn != io_open) + if(fn != thislistener and fn != io_open and fn != caller(0)[1] + and fn != read_validator and fn != write_validator) return _closure(fn, level); die("closure(): query denied (unauthorized access)\n "); } - - # validation listeners for loadxml/savexml (see utils.cxx:fgValidatePath) - var v = props.globals.getNode("/sim/paths/validate", 1); - setlistener(v.getNode("read", 1), func(n) n.setValue(valid(n.getValue(), read_rules) or "")); - setlistener(v.getNode("write", 1), func(n) n.setValue(valid(n.getValue(), write_rules) or "")); - v.remove(); # detach nodes to make them inaccessible for others });