1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

add permit deny lists to file node

This commit is contained in:
Dave Conway-Jones 2018-12-21 08:53:02 +00:00
parent 7f5d47f39d
commit d1cc3da14d
No known key found for this signature in database
GPG Key ID: 9E7F9C73F5168CD4
3 changed files with 61 additions and 9 deletions

View File

@ -16,9 +16,14 @@
module.exports = function(RED) { module.exports = function(RED) {
"use strict"; "use strict";
var mm = require('micromatch');
var fs = require("fs-extra"); var fs = require("fs-extra");
var os = require("os"); var os = require("os");
var path = require("path"); var path = require("path");
//var udir = path.join(RED.settings.userDir,"**");
var allowlist = [].concat((RED.settings.fileNodeAllowList || ["**"]));
var blocklist = [].concat(RED.settings.fileNodeBlockList);
function FileNode(n) { function FileNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
@ -34,6 +39,30 @@ module.exports = function(RED) {
function processMsg(msg, done) { function processMsg(msg, done) {
var filename = node.filename || msg.filename || ""; var filename = node.filename || msg.filename || "";
if (filename === "") {
node.warn(RED._("file.errors.nofilename"));
return;
}
if (filename !== node.lastfile) {
node.lastfile = filename;
node.blocked = true;
if (fs.existsSync(filename)) { filename = fs.realpathSync(filename); }
// Always block settings.js
if (filename === path.join(RED.settings.userDir,"settings.js")) {
node.warn(RED._("file.errors.blocked"));
return;
}
if (mm.any(filename, allowlist, {matchBase:true, dot:true})) {
node.blocked = false;
if (mm.any(filename, blocklist, {matchBase:true, dot:true})) {
node.warn(RED._("file.errors.blocked"));
node.blocked = true;
return;
}
}
}
if (node.blocked === true) { node.warn(RED._("file.errors.blocked")); return; }
if ((!node.filename) && (!node.tout)) { if ((!node.filename) && (!node.tout)) {
node.tout = setTimeout(function() { node.tout = setTimeout(function() {
node.status({fill:"grey",shape:"dot",text:filename}); node.status({fill:"grey",shape:"dot",text:filename});
@ -44,7 +73,8 @@ module.exports = function(RED) {
if (filename === "") { if (filename === "") {
node.warn(RED._("file.errors.nofilename")); node.warn(RED._("file.errors.nofilename"));
done(); done();
} else if (node.overwriteFile === "delete") { }
else if (node.overwriteFile === "delete") {
fs.unlink(filename, function (err) { fs.unlink(filename, function (err) {
if (err) { if (err) {
node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg); node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg);
@ -56,7 +86,8 @@ module.exports = function(RED) {
} }
done(); done();
}); });
} else if (msg.hasOwnProperty("payload") && (typeof msg.payload !== "undefined")) { }
else if (msg.hasOwnProperty("payload") && (typeof msg.payload !== "undefined")) {
var dir = path.dirname(filename); var dir = path.dirname(filename);
if (node.createDir) { if (node.createDir) {
try { try {
@ -232,13 +263,33 @@ module.exports = function(RED) {
this.on("input",function(msg) { this.on("input",function(msg) {
var filename = (node.filename || msg.filename || "").replace(/\t|\r|\n/g,''); var filename = (node.filename || msg.filename || "").replace(/\t|\r|\n/g,'');
if (!node.filename) {
node.status({fill:"grey",shape:"dot",text:filename});
}
if (filename === "") { if (filename === "") {
node.warn(RED._("file.errors.nofilename")); node.warn(RED._("file.errors.nofilename"));
return;
} }
else { if (filename !== node.lastfile) {
node.lastfile = filename;
node.blocked = true;
filename = fs.realpathSync(filename);
// Always block settings.js
if (filename === path.join(RED.settings.userDir,"settings.js")) {
node.warn(RED._("file.errors.blocked"));
return;
}
if (mm.any(filename, allowlist, {matchBase:true, dot:true})) {
node.blocked = false;
if (mm.any(filename, blocklist, {matchBase:true, dot:true})) {
node.warn(RED._("file.errors.blocked"));
node.blocked = true;
return;
}
}
}
if (node.blocked === true) { node.warn(RED._("file.errors.blocked")); return; }
if (!node.filename) { node.status({fill:"grey",shape:"dot",text:filename}); }
//else {
msg.filename = filename; msg.filename = filename;
var lines = Buffer.from([]); var lines = Buffer.from([]);
var spare = ""; var spare = "";
@ -326,7 +377,7 @@ module.exports = function(RED) {
node.send(m); node.send(m);
} }
}); });
} // }
}); });
this.on('close', function() { this.on('close', function() {
node.status({}); node.status({});

View File

@ -849,7 +849,8 @@
"deletefail": "failed to delete file: __error__", "deletefail": "failed to delete file: __error__",
"writefail": "failed to write to file: __error__", "writefail": "failed to write to file: __error__",
"appendfail": "failed to append to file: __error__", "appendfail": "failed to append to file: __error__",
"createfail": "failed to create file: __error__" "createfail": "failed to create file: __error__",
"blocked": "File or directory blocked"
}, },
"tip": "Tip: The filename should be an absolute path, otherwise it will be relative to the working directory of the Node-RED process." "tip": "Tip: The filename should be an absolute path, otherwise it will be relative to the working directory of the Node-RED process."
}, },

View File

@ -58,7 +58,7 @@ describe('file Nodes', function() {
}); });
it('should write to a file', function(done) { it('should write to a file', function(done) {
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]}, var flow = [{id:"fileNode1", type:"file", name:"fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires:[["helperNode1"]]},
{id:"helperNode1", type:"helper"}]; {id:"helperNode1", type:"helper"}];
helper.load(fileNode, flow, function() { helper.load(fileNode, flow, function() {
var n1 = helper.getNode("fileNode1"); var n1 = helper.getNode("fileNode1");