diff --git a/agents/meshcore.js b/agents/meshcore.js index 8f177891..fc9624da 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -2427,7 +2427,7 @@ function createMeshCore(agent) { if ((flags & 4) && (process.platform == 'win32')) { // Update anti-virus information var av, pr; - try { av = require('win-info').av(); } catch (ex) { av = []; } // Antivirus + try { av = require('win-info').av(); } catch (ex) { av = null; } // Antivirus //if (process.platform == 'win32') { try { pr = require('win-info').pendingReboot(); } catch (ex) { pr = null; } } // Pending reboot if ((meshCoreObj.av == null) || (JSON.stringify(meshCoreObj.av) != JSON.stringify(av))) { meshCoreObj.av = av; mesh.SendCommand(meshCoreObj); } } diff --git a/amtscanner.js b/amtscanner.js index 521991da..817bce38 100644 --- a/amtscanner.js +++ b/amtscanner.js @@ -332,9 +332,7 @@ module.exports.CreateAmtScanner = function (parent) { // Event the node change event.msg = 'Intel® AMT changed device ' + node.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); - var node2 = obj.parent.common.Clone(node); - if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = node2; + event.node = obj.parent.webserver.CloneSafeNode(node); if (obj.parent.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. obj.parent.DispatchEvent(['*', node.meshid], obj, event); } diff --git a/apfserver.js b/apfserver.js index ed69ca18..a4728b6a 100644 --- a/apfserver.js +++ b/apfserver.js @@ -248,10 +248,8 @@ module.exports.CreateApfServer = function (parent, db, args) { // Event the new node addedDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. var change = 'APF added device ' + socket.tag.name + ' to group ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain }); // Add the connection to the APF connection list obj.apfConnections[socket.tag.nodeid] = socket; @@ -268,10 +266,8 @@ module.exports.CreateApfServer = function (parent, db, args) { // Event the new node addedDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. var change = 'APF added device ' + socket.tag.name + ' to group ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain }); } } else { // Node is already present @@ -717,9 +713,7 @@ module.exports.CreateApfServer = function (parent, db, args) { // Event the node change event.msg = 'APF changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', '); - var node2 = common.Clone(node); - if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = node2; + event.node = parent.webserver.CloneSafeNode(node); if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. obj.parent.DispatchEvent(['*', node.meshid], obj, event); }); diff --git a/meshagent.js b/meshagent.js index a2917e94..972f9323 100644 --- a/meshagent.js +++ b/meshagent.js @@ -709,11 +709,8 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (obj.agentInfo.capabilities & 0x20) { log = 0; } // Event the node change - var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id }; + var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device) }; if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } - const device2 = common.Clone(device); - if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = device; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. parent.parent.DispatchEvent(['*', device.meshid], obj, event); } @@ -1359,12 +1356,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { db.Set(device); // Event the node change - var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id }; + var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device) }; if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } if ((log == 0) || ((obj.agentInfo) && (obj.agentInfo.capabilities) && (obj.agentInfo.capabilities & 0x20)) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes - var device2 = common.Clone(device); - if (device2.intelamt && device2.intelamt.pass) { delete device2.intelamt.pass; } // Remove the Intel AMT password before eventing this. - event.node = device; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. parent.parent.DispatchEvent(['*', device.meshid], obj, event); } @@ -1404,11 +1398,8 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { db.Set(device); // Event the node change - var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', ') }; + var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), msg: 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', ') }; if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes - var device2 = common.Clone(device); - if (device2.intelamt && device2.intelamt.pass) { delete device2.intelamt.pass; } // Remove the Intel AMT password before eventing this. - event.node = device; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. parent.parent.DispatchEvent(['*', device.meshid], obj, event); } @@ -1437,10 +1428,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { db.Set(device); // Event the node change - var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }; - var device2 = common.Clone(device); - if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = device; + var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), nolog: 1 }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. parent.parent.DispatchEvent(['*', device.meshid], obj, event); } diff --git a/meshcentral.js b/meshcentral.js index b93939fe..d837e9a4 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1449,7 +1449,7 @@ function CreateMeshCentralServer(config, args) { }); stream.on('end', function () { // Add the agent to the agent table with all information and the hash - obj.meshAgentInstallScripts[this.info.id] = obj.common.Clone(this.info); + obj.meshAgentInstallScripts[this.info.id] = Object.assign({}, this.info); obj.meshAgentInstallScripts[this.info.id].hash = this.hash.digest('hex'); obj.meshAgentInstallScripts[this.info.id].path = this.agentpath; obj.meshAgentInstallScripts[this.info.id].data = this.xdata; @@ -1515,7 +1515,7 @@ function CreateMeshCentralServer(config, args) { if ((stats != null)) { // If file exists archcount++; - obj.meshAgentBinaries[archid] = obj.common.Clone(obj.meshAgentsArchitectureNumbers[archid]); + obj.meshAgentBinaries[archid] = Object.assign({}, obj.meshAgentsArchitectureNumbers[archid]); obj.meshAgentBinaries[archid].path = agentpath; obj.meshAgentBinaries[archid].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?id=' + archid; obj.meshAgentBinaries[archid].size = stats.size; diff --git a/meshuser.js b/meshuser.js index bef61832..b965e450 100644 --- a/meshuser.js +++ b/meshuser.js @@ -400,12 +400,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var docs = []; for (i in user.links) { if ((parent.meshes[i]) && (parent.meshes[i].deleted == null)) { - if (parent.meshes[i].amt && parent.meshes[i].amt.password) { - // Remove the Intel AMT password if present - var m = common.Clone(parent.meshes[i]); delete m.amt.password; docs.push(m); - } else { - docs.push(parent.meshes[i]); - } + // Remove the Intel AMT password if present + docs.push(parent.CloneSafeMesh(parent.meshes[i])); } } try { ws.send(JSON.stringify({ action: 'meshes', meshes: docs, tag: command.tag })); } catch (ex) { } @@ -1911,7 +1907,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use else if (command.amtpolicy.type === 3) { amtpolicy = { type: command.amtpolicy.type, password: command.amtpolicy.password, cirasetup: command.amtpolicy.cirasetup }; } mesh.amt = amtpolicy; db.Set(common.escapeLinksFieldName(mesh)); - var amtpolicy2 = common.Clone(amtpolicy); + var amtpolicy2 = Object.assign({}, amtpolicy); // Shallow clone delete amtpolicy2.password; var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, amt: amtpolicy2, action: 'meshchange', msg: change, domain: domain.id }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. @@ -1959,9 +1955,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use db.Set(device); // Event the new node - var device2 = common.Clone(device); - delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: device2, msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id }); + parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id }); }); } break; @@ -2312,9 +2306,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Event the node change. Only do this if the database will not do it. event.msg = 'Changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', '); - var node2 = common.Clone(node); - if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = node2; + event.node = parent.CloneSafeNode(device); if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. parent.parent.DispatchEvent(['*', node.meshid, user._id], obj, event); } diff --git a/mpsserver.js b/mpsserver.js index dfdeab49..69a04c45 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -298,10 +298,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Event the new node addedTlsDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid }); + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: domainid }); // Add the connection to the MPS connection list obj.ciraConnections[socket.tag.nodeid] = socket; @@ -316,10 +314,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Event the new node addedTlsDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid }); + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: domainid }); } } else { // New CIRA connection for unknown node, disconnect. @@ -440,10 +436,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Event the new node addedDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain }); // Add the connection to the MPS connection list obj.ciraConnections[socket.tag.nodeid] = socket; @@ -459,10 +453,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Event the new node addedDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain }); } } else { // Node is already present @@ -925,9 +917,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Event the node change event.msg = 'CIRA changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', '); - var node2 = common.Clone(node); - if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = node2; + event.node = parent.webserver.CloneSafeNode(node); if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. obj.parent.DispatchEvent(['*', node.meshid], obj, event); }); diff --git a/webserver.js b/webserver.js index 3369d8f8..f5a22f73 100644 --- a/webserver.js +++ b/webserver.js @@ -2599,7 +2599,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { db.Set(device); // Event the new node - var device2 = obj.common.Clone(device); + var device2 = Object.assign({}, device); // Shallow clone + device2.intelamt = Object.assign({}, device2.intelamt); // Shallow clone delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. parent.DispatchEvent(['*', ws.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: 'Added device ' + ws.xxstate.name + ' to mesh ' + mesh.name, domain: domain.id }); }); @@ -2624,7 +2625,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { db.Set(device); // Event the new node - var device2 = obj.common.Clone(device); + var device2 = Object.assign({}, device); // Shallow clone + device2.intelamt = Object.assign({}, device2.intelamt); // Shallow clone delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. parent.DispatchEvent(['*', ws.meshid], obj, { etype: 'node', action: 'changenode', nodeid: device2._id, node: device2, msg: 'Changed device ' + device.name + ' in mesh ' + mesh.name, domain: domain.id }); @@ -2736,9 +2738,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Event the node change var event = { etype: 'node', action: 'changenode', nodeid: node._id, domain: domain.id, msg: 'Intel(R) AMT host change ' + node.name + ' from group ' + mesh.name + ': ' + oldname + ' to ' + amthost }; - var node2 = obj.common.Clone(node); - if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. - event.node = node2; + + // Remove the Intel AMT password before eventing this. + event.node = node; + if (event.node.intelamt && event.node.intelamt.pass) { + event.node = Object.assign({}, event.node); // Shallow clone + event.node.intelamt = Object.assign({}, event.node.intelamt); // Shallow clone + delete event.node.intelamt.pass; + } + if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. obj.parent.DispatchEvent(['*', node.meshid], obj, event); } @@ -3218,12 +3226,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { res.set(domain.httpheaders); } else { // Use default security headers + var geourl = (domain.geolocation ? ' *.openstreetmap.org' : ''); + var selfurl = ((args.notls !== true) ? (" wss://" + req.headers.host) : (" ws://" + req.headers.host)); res.set({ "X-Frame-Options": "sameorigin", "Referrer-Policy": "no-referrer", "X-XSS-Protection": "1; mode=block", "X-Content-Type-Options": "nosniff", - "Content-Security-Policy": "default-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self' ws" + ((args.notls !== true) ? 's' : '') + "://" + req.headers.host + "; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-src 'self'; media-src 'self'" + "Content-Security-Policy": "default-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self'" + geourl + selfurl + "; img-src 'self'" + geourl + " data:; style-src 'self' 'unsafe-inline'; frame-src 'self'; media-src 'self'" }); } @@ -3701,7 +3711,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Clone a safe version of a user object, remove everything that is secret. obj.CloneSafeUser = function (user) { if (typeof user != 'object') { return user; } - var user2 = obj.common.Clone(user); + var user2 = Object.assign({}, user); // Shallow clone delete user2.hash; delete user2.passhint; delete user2.salt; @@ -3715,6 +3725,30 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { return user2; } + // Clone a safe version of a node object, remove everything that is secret. + obj.CloneSafeNode = function (node) { + if (typeof node != 'object') { return node; } + var r = node; + if (r.intelamt && r.intelamt.pass) { + r = Object.assign({}, r); // Shallow clone + r.intelamt = Object.assign({}, r.intelamt); // Shallow clone + delete r.intelamt.pass; // Remove the Intel AMT password from the node + } + return r; + } + + // Clone a safe version of a mesh object, remove everything that is secret. + obj.CloneSafeMesh = function (mesh) { + if (typeof mesh != 'object') { return mesh; } + var r = mesh; + if (r.amt && r.amt.password) { + r = Object.assign({}, r); // Shallow clone + r.amt = Object.assign({}, r.amt); // Shallow clone + delete r.amt.password; // Remove the Intel AMT password from the policy + } + return r; + } + // Return the correct render page given mobile, minify and override path. function getRenderPage(pagename, req) { var mobile = isMobileBrowser(req), minify = obj.args.minify && !req.query.nominify, p;