From c3efdb39c1a7bd6f9e02368704c838ebd2436e45 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 27 Dec 2019 15:18:43 -0800 Subject: [PATCH] More access control improvements, RPi icon. --- agents/meshcore.js | 7 +- interceptor.js | 84 +-- meshrelay.js | 4 +- meshuser.js | 930 ++++++++++++-------------------- mpsserver.js | 58 +- multiserver.js | 14 +- package.json | 2 +- public/images/icons16.png | Bin 2201 -> 4062 bytes public/images/icons256-7-1.png | Bin 0 -> 47554 bytes public/images/icons50.png | Bin 24718 -> 29091 bytes public/images/icons64.png | Bin 41598 -> 47417 bytes public/styles/style.css | 36 +- translate/translate.json | 5 +- views/default-mobile.handlebars | 112 ++-- views/default.handlebars | 204 +++---- webserver.js | 76 +-- 16 files changed, 699 insertions(+), 833 deletions(-) create mode 100644 public/images/icons256-7-1.png diff --git a/agents/meshcore.js b/agents/meshcore.js index 73ab3b43..8552437a 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1919,13 +1919,10 @@ function createMeshCore(agent) { switch (cmd) { case 'help': { // Displays available commands var fin = '', f = '', availcommands = 'version,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper'; - if (process.platform == 'win32') - { - availcommands += ',safemode,wpfhwacceleration'; - } + if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { - if (f.length > 100) { fin += (f + ',\r\n'); f = ''; } + if (f.length > 90) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); } if (f != '') { fin += f; } diff --git a/interceptor.js b/interceptor.js index c32ad805..73fe7e62 100644 --- a/interceptor.js +++ b/interceptor.js @@ -12,10 +12,10 @@ /*jshint node: true */ /*jshint strict: false */ /*jshint esversion: 6 */ -"use strict"; +'use strict'; -const crypto = require("crypto"); -const common = require("./common.js"); +const crypto = require('crypto'); +const common = require('./common.js'); var HttpInterceptorAuthentications = {}; //var RedirInterceptorAuthentications = {}; @@ -28,8 +28,8 @@ module.exports.CreateHttpInterceptor = function (args) { obj.randomValueHex = function (len) { return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len); }; obj.args = args; - obj.amt = { acc: "", mode: 0, count: 0, error: false }; // mode: 0:Header, 1:LengthBody, 2:ChunkedBody, 3:UntilClose - obj.ws = { acc: "", mode: 0, count: 0, error: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 }; + obj.amt = { acc: '', mode: 0, count: 0, error: false }; // mode: 0:Header, 1:LengthBody, 2:ChunkedBody, 3:UntilClose + obj.ws = { acc: '', mode: 0, count: 0, error: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 }; obj.blockAmtStorage = false; // Private method @@ -38,7 +38,7 @@ module.exports.CreateHttpInterceptor = function (args) { // Process data coming from Intel AMT obj.processAmtData = function (data) { obj.amt.acc += data; // Add data to accumulator - data = ""; + data = ''; var datalen = 0; do { datalen = data.length; @@ -53,7 +53,7 @@ module.exports.CreateHttpInterceptor = function (args) { if (obj.amt.mode == 0) { // Header Mode // Decode the HTTP header headerend = obj.amt.acc.indexOf('\r\n\r\n'); - if (headerend < 0) return ""; + if (headerend < 0) return ''; var headerlines = obj.amt.acc.substring(0, headerend).split('\r\n'); obj.amt.acc = obj.amt.acc.substring(headerend + 4); obj.amt.directive = headerlines[0].split(' '); @@ -98,7 +98,7 @@ module.exports.CreateHttpInterceptor = function (args) { } else if (obj.amt.mode == 2) { // Chunked Body Mode // Send data one chunk at a time headerend = obj.amt.acc.indexOf('\r\n'); - if (headerend < 0) return ""; + if (headerend < 0) return ''; var chunksize = parseInt(obj.amt.acc.substring(0, headerend), 16); if ((chunksize == 0) && (obj.amt.acc.length >= headerend + 4)) { // Send the ending chunk (NOTE: We do not support trailing headers) @@ -114,16 +114,16 @@ module.exports.CreateHttpInterceptor = function (args) { } } else if (obj.amt.mode == 3) { // Until Close Mode r = obj.amt.acc; - obj.amt.acc = ""; + obj.amt.acc = ''; return r; } - return ""; + return ''; }; // Process data coming from the Browser obj.processBrowserData = function (data) { obj.ws.acc += data; // Add data to accumulator - data = ""; + data = ''; var datalen = 0; do { datalen = data.length; @@ -138,7 +138,7 @@ module.exports.CreateHttpInterceptor = function (args) { if (obj.ws.mode == 0) { // Header Mode // Decode the HTTP header headerend = obj.ws.acc.indexOf('\r\n\r\n'); - if (headerend < 0) return ""; + if (headerend < 0) return ''; var headerlines = obj.ws.acc.substring(0, headerend).split('\r\n'); obj.ws.acc = obj.ws.acc.substring(headerend + 4); obj.ws.directive = headerlines[0].split(' '); @@ -199,7 +199,7 @@ module.exports.CreateHttpInterceptor = function (args) { } else if (obj.amt.mode == 2) { // Chunked Body Mode // Send data one chunk at a time headerend = obj.amt.acc.indexOf('\r\n'); - if (headerend < 0) return ""; + if (headerend < 0) return ''; var chunksize = parseInt(obj.amt.acc.substring(0, headerend), 16); if (isNaN(chunksize)) { // TODO: Check this path // Chunk is not in this batch, move one @@ -226,10 +226,10 @@ module.exports.CreateHttpInterceptor = function (args) { } } else if (obj.ws.mode == 3) { // Until Close Mode r = obj.ws.acc; - obj.ws.acc = ""; + obj.ws.acc = ''; return r; } - return ""; + return ''; }; // Parse authentication values from the HTTP header @@ -249,9 +249,9 @@ module.exports.CreateHttpInterceptor = function (args) { // Compute the MD5 digest hash for a set of values obj.ComputeDigesthash = function (username, password, realm, method, path, qop, nonce, nc, cnonce) { - var ha1 = crypto.createHash('md5').update(username + ":" + realm + ":" + password).digest("hex"); - var ha2 = crypto.createHash('md5').update(method + ":" + path).digest("hex"); - return crypto.createHash('md5').update(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2).digest("hex"); + var ha1 = crypto.createHash('md5').update(username + ':' + realm + ':' + password).digest('hex'); + var ha2 = crypto.createHash('md5').update(method + ':' + path).digest('hex'); + return crypto.createHash('md5').update(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2).digest('hex'); }; return obj; @@ -266,8 +266,8 @@ module.exports.CreateRedirInterceptor = function (args) { obj.randomValueHex = function (len) { return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len); }; obj.args = args; - obj.amt = { acc: "", mode: 0, count: 0, error: false, direct: false }; - obj.ws = { acc: "", mode: 0, count: 0, error: false, direct: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 }; + obj.amt = { acc: '', mode: 0, count: 0, error: false, direct: false }; + obj.ws = { acc: '', mode: 0, count: 0, error: false, direct: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 }; obj.RedirectCommands = { StartRedirectionSession: 0x10, StartRedirectionSessionReply: 0x11, EndRedirectionSession: 0x12, AuthenticateSession: 0x13, AuthenticateSessionReply: 0x14 }; obj.StartRedirectionSessionReplyStatus = { SUCCESS: 0, TYPE_UNKNOWN: 1, BUSY: 2, UNSUPPORTED: 3, ERROR: 0xFF }; @@ -280,7 +280,7 @@ module.exports.CreateRedirInterceptor = function (args) { // Process data coming from Intel AMT obj.processAmtData = function (data) { obj.amt.acc += data; // Add data to accumulator - data = ""; + data = ''; var datalen = 0; do { datalen = data.length; data += obj.processAmtDataEx(); } while (datalen != data.length); // Process as much data as possible return data; @@ -298,11 +298,11 @@ module.exports.CreateRedirInterceptor = function (args) { //console.log(obj.amt.acc.charCodeAt(0)); switch (obj.amt.acc.charCodeAt(0)) { case obj.RedirectCommands.StartRedirectionSessionReply: { - if (obj.amt.acc.length < 4) return ""; + if (obj.amt.acc.length < 4) return ''; if (obj.amt.acc.charCodeAt(1) == obj.StartRedirectionSessionReplyStatus.SUCCESS) { - if (obj.amt.acc.length < 13) return ""; + if (obj.amt.acc.length < 13) return ''; var oemlen = obj.amt.acc.charCodeAt(12); - if (obj.amt.acc.length < 13 + oemlen) return ""; + if (obj.amt.acc.length < 13 + oemlen) return ''; r = obj.amt.acc.substring(0, 13 + oemlen); obj.amt.acc = obj.amt.acc.substring(13 + oemlen); return r; @@ -310,9 +310,9 @@ module.exports.CreateRedirInterceptor = function (args) { break; } case obj.RedirectCommands.AuthenticateSessionReply: { - if (obj.amt.acc.length < 9) return ""; + if (obj.amt.acc.length < 9) return ''; var l = common.ReadIntX(obj.amt.acc, 5); - if (obj.amt.acc.length < 9 + l) return ""; + if (obj.amt.acc.length < 9 + l) return ''; var authstatus = obj.amt.acc.charCodeAt(1); var authType = obj.amt.acc.charCodeAt(4); @@ -337,17 +337,17 @@ module.exports.CreateRedirInterceptor = function (args) { } default: { obj.amt.error = true; - return ""; + return ''; } } } - return ""; + return ''; }; // Process data coming from the Browser obj.processBrowserData = function (data) { obj.ws.acc += data; // Add data to accumulator - data = ""; + data = ''; var datalen = 0; do { datalen = data.length; data += obj.processBrowserDataEx(); } while (datalen != data.length); // Process as much data as possible return data; @@ -356,39 +356,39 @@ module.exports.CreateRedirInterceptor = function (args) { // Process data coming from the Browser in the accumulator obj.processBrowserDataEx = function () { var r; - if (obj.ws.acc.length == 0) return ""; + if (obj.ws.acc.length == 0) return ''; if (obj.ws.direct == true) { var data = obj.ws.acc; - obj.ws.acc = ""; + obj.ws.acc = ''; return data; } else { switch (obj.ws.acc.charCodeAt(0)) { case obj.RedirectCommands.StartRedirectionSession: { - if (obj.ws.acc.length < 8) return ""; + if (obj.ws.acc.length < 8) return ''; r = obj.ws.acc.substring(0, 8); obj.ws.acc = obj.ws.acc.substring(8); return r; } case obj.RedirectCommands.EndRedirectionSession: { - if (obj.ws.acc.length < 4) return ""; + if (obj.ws.acc.length < 4) return ''; r = obj.ws.acc.substring(0, 4); obj.ws.acc = obj.ws.acc.substring(4); return r; } case obj.RedirectCommands.AuthenticateSession: { - if (obj.ws.acc.length < 9) return ""; + if (obj.ws.acc.length < 9) return ''; var l = common.ReadIntX(obj.ws.acc, 5); - if (obj.ws.acc.length < 9 + l) return ""; + if (obj.ws.acc.length < 9 + l) return ''; var authType = obj.ws.acc.charCodeAt(4); if (authType == obj.AuthenticationType.DIGEST && obj.args.user && obj.args.pass) { - var authurl = "/RedirectionService"; + var authurl = '/RedirectionService'; if (obj.amt.digestRealm) { // Replace this authentication digest with a server created one // We have everything we need to authenticate var nc = obj.ws.authCNonceCount; obj.ws.authCNonceCount++; - var digest = obj.ComputeDigesthash(obj.args.user, obj.args.pass, obj.amt.digestRealm, "POST", authurl, obj.amt.digestQOP, obj.amt.digestNonce, nc, obj.ws.authCNonce); + var digest = obj.ComputeDigesthash(obj.args.user, obj.args.pass, obj.amt.digestRealm, 'POST', authurl, obj.amt.digestQOP, obj.amt.digestNonce, nc, obj.ws.authCNonce); // Replace this authentication digest with a server created one // We have everything we need to authenticate @@ -434,18 +434,18 @@ module.exports.CreateRedirInterceptor = function (args) { } default: { obj.ws.error = true; - return ""; + return ''; } } } - return ""; + return ''; }; // Compute the MD5 digest hash for a set of values obj.ComputeDigesthash = function (username, password, realm, method, path, qop, nonce, nc, cnonce) { - var ha1 = crypto.createHash('md5').update(username + ":" + realm + ":" + password).digest("hex"); - var ha2 = crypto.createHash('md5').update(method + ":" + path).digest("hex"); - return crypto.createHash('md5').update(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2).digest("hex"); + var ha1 = crypto.createHash('md5').update(username + ':' + realm + ':' + password).digest('hex'); + var ha2 = crypto.createHash('md5').update(method + ':' + path).digest('hex'); + return crypto.createHash('md5').update(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2).digest('hex'); }; return obj; diff --git a/meshrelay.js b/meshrelay.js index 37356362..ad2fc002 100644 --- a/meshrelay.js +++ b/meshrelay.js @@ -80,7 +80,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie var agent = parent.wsagents[command.nodeid]; if (agent != null) { // Check if we have permission to send a message to that node - rights = user.links[agent.dbMeshKey]; + rights = user.links[agent.dbMeshKey]; // TODO: Need to include user group / node rights mesh = parent.meshes[agent.dbMeshKey]; if ((rights != null) && (mesh != null) || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking if (ws.sessionId) { command.sessionid = ws.sessionId; } // Set the session id, required for responses. @@ -98,7 +98,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie var routing = parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type if (routing != null) { // Check if we have permission to send a message to that node - rights = user.links[routing.meshid]; + rights = user.links[routing.meshid]; // TODO: Need to include user groups / node rights mesh = parent.meshes[routing.meshid]; if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking if (ws.sessionId) { command.fromSessionid = ws.sessionId; } // Set the session id, required for responses. diff --git a/meshuser.js b/meshuser.js index ebec84f7..ce863cef 100644 --- a/meshuser.js +++ b/meshuser.js @@ -152,11 +152,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var agent = parent.wsagents[command.nodeid]; if (agent != null) { // Check if we have permission to send a message to that node - var meshrights = parent.GetMeshRights(user, agent.dbMeshKey); + var meshrights = parent.GetMeshRights(user, agent.dbMeshKey); // TODO: We will need to get the rights for this specific node. var mesh = parent.meshes[agent.dbMeshKey]; if ((mesh != null) && ((meshrights & MESHRIGHT_REMOTECONTROL) || (meshrights & MESHRIGHT_REMOTEVIEWONLY))) { // 8 is remote control permission, 256 is desktop read only command.sessionid = ws.sessionId; // Set the session id, required for responses - command.rights = meshrights; // Add user rights flags to the message + command.rights = meshrights; // Add user rights flags to the message command.consent = mesh.consent; // Add user consent if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags command.username = user.name; // Add user name @@ -503,101 +503,74 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'powertimeline': { - // Perform pre-validation - if (common.validateString(command.nodeid, 0, 128) == false) break; - var snode = command.nodeid.split('/'); - if ((snode.length != 3) || (snode[1] != domain.id)) break; - - // Check that we have permissions for this node. - db.Get(command.nodeid, function (err, nodes) { - if (nodes == null || nodes.length != 1) return; - const node = nodes[0]; - - if (parent.GetMeshRights(user, node.meshid) != 0) { - // Query the database for the power timeline for a given node - // The result is a compacted array: [ startPowerState, startTimeUTC, powerState ] + many[ deltaTime, powerState ] - db.getPowerTimeline(command.nodeid, function (err, docs) { - if ((err == null) && (docs != null) && (docs.length > 0)) { - var timeline = [], time = null, previousPower; - for (i in docs) { - var doc = docs[i], j = parseInt(i); - doc.time = Date.parse(doc.time); - if (time == null) { // First element - // Skip all starting power 0 events. - if ((doc.power == 0) && ((doc.oldPower == null) || (doc.oldPower == 0))) continue; - time = doc.time; - if (doc.oldPower) { timeline.push(doc.oldPower, time / 1000, doc.power); } else { timeline.push(0, time / 1000, doc.power); } - } else if (previousPower != doc.power) { // Delta element - // If this event is of a short duration (2 minutes or less), skip it. - if ((docs.length > (j + 1)) && ((Date.parse(docs[j + 1].time) - doc.time) < 120000)) continue; - timeline.push((doc.time - time) / 1000, doc.power); - time = doc.time; - } - previousPower = doc.power; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if (visible == false) return; + // Query the database for the power timeline for a given node + // The result is a compacted array: [ startPowerState, startTimeUTC, powerState ] + many[ deltaTime, powerState ] + db.getPowerTimeline(node._id, function (err, docs) { + if ((err == null) && (docs != null) && (docs.length > 0)) { + var timeline = [], time = null, previousPower; + for (i in docs) { + var doc = docs[i], j = parseInt(i); + doc.time = Date.parse(doc.time); + if (time == null) { // First element + // Skip all starting power 0 events. + if ((doc.power == 0) && ((doc.oldPower == null) || (doc.oldPower == 0))) continue; + time = doc.time; + if (doc.oldPower) { timeline.push(doc.oldPower, time / 1000, doc.power); } else { timeline.push(0, time / 1000, doc.power); } + } else if (previousPower != doc.power) { // Delta element + // If this event is of a short duration (2 minutes or less), skip it. + if ((docs.length > (j + 1)) && ((Date.parse(docs[j + 1].time) - doc.time) < 120000)) continue; + timeline.push((doc.time - time) / 1000, doc.power); + time = doc.time; } - try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: command.nodeid, timeline: timeline, tag: command.tag })); } catch (ex) { } - } else { - // No records found, send current state if we have it - var state = parent.parent.GetConnectivityState(command.nodeid); - if (state != null) { try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: command.nodeid, timeline: [state.powerState, Date.now(), state.powerState], tag: command.tag })); } catch (ex) { } } + previousPower = doc.power; } - }); - } + try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: node._id, timeline: timeline, tag: command.tag })); } catch (ex) { } + } else { + // No records found, send current state if we have it + var state = parent.parent.GetConnectivityState(command.nodeid); + if (state != null) { try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: node._id, timeline: [state.powerState, Date.now(), state.powerState], tag: command.tag })); } catch (ex) { } } + } + }); }); break; } case 'getsysinfo': { - // Perform pre-validation - if (common.validateString(command.nodeid, 0, 128) == false) break; - var snode = command.nodeid.split('/'); - if ((snode.length != 3) || (snode[1] != domain.id)) break; - - // Check that we have permissions for this node. - db.Get(command.nodeid, function (err, nodes) { - if (nodes == null || nodes.length != 1) return; - const node = nodes[0]; - - if (parent.GetMeshRights(user, node.meshid) != 0) { - // Query the database system information - db.Get('si' + command.nodeid, function (err, docs) { - if ((docs != null) && (docs.length > 0)) { - var doc = docs[0]; - doc.action = 'getsysinfo'; - doc.nodeid = command.nodeid; - doc.tag = command.tag; - delete doc.type; - delete doc.domain; - delete doc._id; - try { ws.send(JSON.stringify(doc)); } catch (ex) { } - } else { - try { ws.send(JSON.stringify({ action: 'getsysinfo', nodeid: command.nodeid, tag: command.tag, noinfo: true })); } catch (ex) { } - } - }); - } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if (visible == false) return; + // Query the database system information + db.Get('si' + command.nodeid, function (err, docs) { + if ((docs != null) && (docs.length > 0)) { + var doc = docs[0]; + doc.action = 'getsysinfo'; + doc.nodeid = node._id; + doc.tag = command.tag; + delete doc.type; + delete doc.domain; + delete doc._id; + try { ws.send(JSON.stringify(doc)); } catch (ex) { } + } else { + try { ws.send(JSON.stringify({ action: 'getsysinfo', nodeid: node._id, tag: command.tag, noinfo: true })); } catch (ex) { } + } + }); }); break; } case 'lastconnect': { - // Perform pre-validation - if (common.validateString(command.nodeid, 0, 128) == false) return; - var snode = command.nodeid.split('/'); - if ((snode.length != 3) || (snode[1] != domain.id)) break; - - // Check that we have permissions for this node. - db.Get(command.nodeid, function (err, nodes) { - if (nodes == null || nodes.length != 1) return; - const node = nodes[0]; - - if (parent.GetMeshRights(user, node.meshid) != 0) { - // Query the database for the last time this node connected - db.Get('lc' + command.nodeid, function (err, docs) { - if ((docs != null) && (docs.length > 0)) { - try { ws.send(JSON.stringify({ action: 'lastconnect', nodeid: command.nodeid, time: docs[0].time, addr: docs[0].addr })); } catch (ex) { } - } - }); - } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if (visible == false) return; + // Query the database for the last time this node connected + db.Get('lc' + command.nodeid, function (err, docs) { + if ((docs != null) && (docs.length > 0)) { + try { ws.send(JSON.stringify({ action: 'lastconnect', nodeid: command.nodeid, time: docs[0].time, addr: docs[0].addr })); } catch (ex) { } + } + }); }); break; } @@ -963,31 +936,27 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use try { ws.send(JSON.stringify({ action: 'events', events: docs, user: command.user, tag: command.tag })); } catch (ex) { } }); } - } else if (common.validateString(command.nodeid, 0, 128) == true) { // Device filtered events + } else if (command.nodeid != null) { // Device filtered events // Check that the user has access to this nodeid - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - const node = nodes[0]; + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if (node == null) return; - var meshrights = parent.GetMeshRights(user, node.meshid); - if (meshrights != 0) { - // Put a limit on the number of returned entries if present - var limit = 10000; - if (common.validateInt(command.limit, 1, 60000) == true) { limit = command.limit; } + // Put a limit on the number of returned entries if present + var limit = 10000; + if (common.validateInt(command.limit, 1, 60000) == true) { limit = command.limit; } - if ((meshrights & MESHRIGHT_LIMITEVENTS) != 0) { - // Send the list of most recent events for this nodeid that only apply to us, up to 'limit' count - db.GetNodeEventsSelfWithLimit(command.nodeid, domain.id, user._id, limit, function (err, docs) { - if (err != null) return; - try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: command.nodeid, tag: command.tag })); } catch (ex) { } - }); - } else { - // Send the list of most recent events for this nodeid, up to 'limit' count - db.GetNodeEventsWithLimit(command.nodeid, domain.id, limit, function (err, docs) { - if (err != null) return; - try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: command.nodeid, tag: command.tag })); } catch (ex) { } - }); - } + if ((rights & MESHRIGHT_LIMITEVENTS) != 0) { + // Send the list of most recent events for this nodeid that only apply to us, up to 'limit' count + db.GetNodeEventsSelfWithLimit(node._id, domain.id, user._id, limit, function (err, docs) { + if (err != null) return; + try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: node._id, tag: command.tag })); } catch (ex) { } + }); + } else { + // Send the list of most recent events for this nodeid, up to 'limit' count + db.GetNodeEventsWithLimit(node._id, domain.id, limit, function (err, docs) { + if (err != null) return; + try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: node._id, tag: command.tag })); } catch (ex) { } + }); } }); } else { @@ -997,7 +966,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // All events var exGroupFilter2 = [], filter = [], filter2 = user.subscriptions; - // Remove MeshID's that we do not have rights to see events for (TODO: user groups) + // Add all meshes for groups this user is part of + // TODO (UserGroups) + + // Remove MeshID's that we do not have rights to see events for for (var link in obj.user.links) { if (((obj.user.links[link].rights & MESHRIGHT_LIMITEVENTS) != 0) && ((obj.user.links[link].rights != 0xFFFFFFFF))) { exGroupFilter2.push(link); } } for (var i in filter2) { if (exGroupFilter2.indexOf(filter2[i]) == -1) { filter.push(filter2[i]); } } @@ -1198,7 +1170,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } } - // TODO: Remove user groups?? + // TODO (UserGroups): Remove user groups?? db.Remove('ws' + deluser._id); // Remove user web state db.Remove('nt' + deluser._id); // Remove notes for this user @@ -1507,17 +1479,20 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check the meshid else if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; } if (common.validateInt(command.notify) == false) { err = 'Invalid notification flags'; } - if (parent.GetMeshRights(user, command.meshid) == 0) err = 'Access denied'; + if (parent.IsMeshViewable(user, command.meshid) == false) err = 'Access denied'; } catch (ex) { err = 'Validation exception: ' + ex; } // Handle any errors if (err != null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'changemeshnotify', responseid: command.responseid, result: err })); } catch (ex) { } } break; } // Change the notification (TODO: Add user group support, not sure how to do this here) - if (command.notify == 0) { - delete user.links[command.meshid].notify; - } else { - user.links[command.meshid].notify = command.notify; + // TODO (UserGroups) + if (user.links[command.meshid]) { + if (command.notify == 0) { + delete user.links[command.meshid].notify; + } else { + user.links[command.meshid].notify = command.notify; + } } // Save the user @@ -1674,33 +1649,23 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } } + // User-to-device chat is not support in LAN-only mode yet. We need the agent to replace the IP address of the server?? + if (args.lanonly == true) { return; } + // Setup a user-to-node session - if (common.validateString(command.nodeid, 1, 2048)) { - if (args.lanonly == true) { return; } // User-to-device chat is not support in LAN-only mode yet. We need the agent to replace the IP address of the server?? + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + // Check if this user has rights to do this + if ((rights & MESHRIGHT_CHATNOTIFY) == 0) return; - // Get the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; - - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_CHATNOTIFY) == 0) return; - - // Create the server url - var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified - var xdomain = (domain.dns == null) ? domain.id : ''; - if (xdomain != '') xdomain += "/"; - var url = "http" + (args.notls ? '' : 's') + "://" + parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name); - - // Create the notification message - routeCommandToNode({ "action": "openUrl", "nodeid": command.nodeid, "userid": user._id, "username": user.name, "url": url }); - } - }); - } + // Create the server url + var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified + var xdomain = (domain.dns == null) ? domain.id : ''; + if (xdomain != '') xdomain += "/"; + var url = "http" + (args.notls ? '' : 's') + "://" + parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name); + // Create the notification message + routeCommandToNode({ "action": "openUrl", "nodeid": command.nodeid, "userid": user._id, "username": user.name, "url": url }); + }); break; } case 'serverversion': @@ -2084,20 +2049,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // For each nodeid, change the group for (var i = 0; i < command.nodeids.length; i++) { - db.Get(command.nodeids[i], function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - const node = nodes[0]; - + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { // Check if already in the right mesh - if (node.meshid == command.meshid) return; + if ((node == null) || (node.meshid == command.meshid)) return; // Make sure both source and target mesh are the same type try { if (parent.meshes[node.meshid].mtype != parent.meshes[command.meshid].mtype) return; } catch (e) { return; }; // Make sure that we have rights on both source and destination mesh - const sourceMeshRights = parent.GetMeshRights(user, node.meshid); const targetMeshRights = parent.GetMeshRights(user, command.meshid); - if (((sourceMeshRights & MESHRIGHT_MANAGECOMPUTERS) == 0) || ((targetMeshRights & MESHRIGHT_MANAGECOMPUTERS) == 0)) return; + if (((rights & MESHRIGHT_MANAGECOMPUTERS) == 0) || ((targetMeshRights & MESHRIGHT_MANAGECOMPUTERS) == 0)) return; // Perform the switch, start by saving the node with the new meshid. const oldMeshId = node.meshid; @@ -2139,146 +2101,103 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use case 'removedevices': { if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's - for (i in command.nodeids) { - nodeid = command.nodeids[i]; - if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid - if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + // Check we have the rights to delete this device + if ((rights & MESHRIGHT_MANAGECOMPUTERS) == 0) return; - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Delete this node including network interface information, events and timeline + db.Remove(node._id); // Remove node with that id + db.Remove('if' + node._id); // Remove interface information + db.Remove('nt' + node._id); // Remove notes + db.Remove('lc' + node._id); // Remove last connect time + db.Remove('si' + node._id); // Remove system information + db.RemoveSMBIOS(node._id); // Remove SMBios data + db.RemoveAllNodeEvents(node._id); // Remove all events for this node + db.removeAllPowerEventsForNode(node._id); // Remove all power events for this node + db.Get('ra' + obj.dbNodeKey, function (err, nodes) { + if ((nodes != null) && (nodes.length == 1)) { db.Remove('da' + nodes[0].daid); } // Remove diagnostic agent to real agent link + db.Remove('ra' + node._id); // Remove real agent to diagnostic agent link + }); - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return; + // Event node deletion + var event = { etype: 'node', userid: user._id, username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from group ' + mesh.name, domain: domain.id }; + // TODO: We can't use the changeStream for node delete because we will not know the meshid the device was in. + //if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to remove the node. Another event will come. + parent.parent.DispatchEvent(['*', node.meshid], obj, event); - // Delete this node including network interface information, events and timeline - db.Remove(node._id); // Remove node with that id - db.Remove('if' + node._id); // Remove interface information - db.Remove('nt' + node._id); // Remove notes - db.Remove('lc' + node._id); // Remove last connect time - db.Remove('si' + node._id); // Remove system information - db.RemoveSMBIOS(node._id); // Remove SMBios data - db.RemoveAllNodeEvents(node._id); // Remove all events for this node - db.removeAllPowerEventsForNode(node._id); // Remove all power events for this node - db.Get('ra' + obj.dbNodeKey, function (err, nodes) { - if ((nodes != null) && (nodes.length == 1)) { db.Remove('da' + nodes[0].daid); } // Remove diagnostic agent to real agent link - db.Remove('ra' + node._id); // Remove real agent to diagnostic agent link - }); - - // Event node deletion - var event = { etype: 'node', userid: user._id, username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from group ' + mesh.name, domain: domain.id }; - // TODO: We can't use the changeStream for node delete because we will not know the meshid the device was in. - //if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to remove the node. Another event will come. - parent.parent.DispatchEvent(['*', node.meshid], obj, event); - - // Disconnect all connections if needed - var state = parent.parent.GetConnectivityState(nodeid); - if ((state != null) && (state.connectivity != null)) { - if ((state.connectivity & 1) != 0) { parent.wsagents[nodeid].close(); } // Disconnect mesh agent - if ((state.connectivity & 2) != 0) { parent.parent.mpsserver.close(parent.parent.mpsserver.ciraConnections[nodeid]); } // Disconnect CIRA connection - } + // Disconnect all connections if needed + var state = parent.parent.GetConnectivityState(nodeid); + if ((state != null) && (state.connectivity != null)) { + if ((state.connectivity & 1) != 0) { parent.wsagents[nodeid].close(); } // Disconnect mesh agent + if ((state.connectivity & 2) != 0) { parent.parent.mpsserver.close(parent.parent.mpsserver.ciraConnections[nodeid]); } // Disconnect CIRA connection } }); } - break; } case 'wakedevices': { - if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's // TODO: We can optimize this a lot. // - We should get a full list of all MAC's to wake first. // - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan. + if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's for (i in command.nodeids) { - nodeid = command.nodeids[i]; - var wakeActions = 0; - if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + // Check we have the rights to delete this device + if ((rights & MESHRIGHT_WAKEDEVICE) == 0) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { + // If this device is connected on MQTT, send a wake action. + if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, 'powerAction', 'wake'); } - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_WAKEDEVICE) != 0) { + // Get the device interface information + db.Get('if' + node._id, function (err, nodeifs) { + if ((nodeifs != null) && (nodeifs.length == 1)) { + var macs = [], nodeif = nodeifs[0]; + for (var i in nodeif.netif) { if (nodeif.netif[i].mac) { macs.push(nodeif.netif[i].mac); } } - // If this device is connected on MQTT, send a wake action. - if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, 'powerAction', 'wake'); } + // Have the server send a wake-on-lan packet (Will not work in WAN-only) + if (parent.parent.meshScanner != null) { parent.parent.meshScanner.wakeOnLan(macs); } - // Get the device interface information - db.Get('if' + node._id, function (err, nodeifs) { - if ((nodeifs != null) && (nodeifs.length == 1)) { - var nodeif = nodeifs[0]; - var macs = []; - for (var i in nodeif.netif) { if (nodeif.netif[i].mac) { macs.push(nodeif.netif[i].mac); } } - - // Have the server send a wake-on-lan packet (Will not work in WAN-only) - if (parent.parent.meshScanner != null) { parent.parent.meshScanner.wakeOnLan(macs); wakeActions++; } - - // Get the list of mesh this user as access to - var targetMeshes = []; - for (i in user.links) { targetMeshes.push(i); } // TODO: Include used security groups!! - - // Go thru all the connected agents and send wake-on-lan on all the ones in the target mesh list - for (i in parent.wsagents) { - var agent = parent.wsagents[i]; - if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) { - //console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(',')); - try { agent.send(JSON.stringify({ action: 'wakeonlan', macs: macs })); } catch (ex) { } - wakeActions++; - } - } - } - }); + // Get the list of mesh this user as access to + var targetMeshes = []; + for (i in user.links) { targetMeshes.push(i); } // TODO: Include used security groups!! + // Go thru all the connected agents and send wake-on-lan on all the ones in the target mesh list + for (i in parent.wsagents) { + var agent = parent.wsagents[i]; + if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) { + //console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(',')); + try { agent.send(JSON.stringify({ action: 'wakeonlan', macs: macs })); } catch (ex) { } + } } } }); - } + }); // Confirm we may be doing something (TODO) try { ws.send(JSON.stringify({ action: 'wakedevices' })); } catch (ex) { } } - break; } case 'uninstallagent': { if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's for (i in command.nodeids) { - nodeid = command.nodeids[i]; - if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + // Check we have the rights to delete this device + if ((rights & MESHRIGHT_UNINSTALL) == 0) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_UNINSTALL) != 0) { - // Send uninstall command to connected agent - var agent = parent.wsagents[node._id]; - if (agent != null) { - //console.log('Asking agent ' + agent.dbNodeKey + ' to uninstall.'); - try { agent.send(JSON.stringify({ action: 'uninstallagent' })); } catch (ex) { } - } - } - } - }); - } + // Send uninstall command to connected agent + const agent = parent.wsagents[node._id]; + if (agent != null) { + //console.log('Asking agent ' + agent.dbNodeKey + ' to uninstall.'); + try { agent.send(JSON.stringify({ action: 'uninstallagent' })); } catch (ex) { } + } + }); } - break; } case 'poweraction': @@ -2286,34 +2205,21 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's if (common.validateInt(command.actiontype, 2, 4) == false) break; // Check actiontype for (i in command.nodeids) { - nodeid = command.nodeids[i]; - var powerActions = 0; - if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + // Check we have the rights to delete this device + if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // If this device is connected on MQTT, send a power action. - if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(nodeid, 'powerAction', ['', '', 'poweroff', 'reset', 'sleep'][command.actiontype]); } + // If this device is connected on MQTT, send a power action. + if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, 'powerAction', ['', '', 'poweroff', 'reset', 'sleep'][command.actiontype]); } + + // Get this device and send the power command + const agent = parent.wsagents[node._id]; + if (agent != null) { + try { agent.send(JSON.stringify({ action: 'poweraction', actiontype: command.actiontype })); } catch (ex) { } + } + }); - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_REMOTECONTROL) != 0) { // "Remote Control permission" - // Get this device - var agent = parent.wsagents[node._id]; - if (agent != null) { - // Send the power command - try { agent.send(JSON.stringify({ action: 'poweraction', actiontype: command.actiontype })); } catch (ex) { } - powerActions++; - } - } - } - }); - } // Confirm we may be doing something (TODO) try { ws.send(JSON.stringify({ action: 'poweraction' })); } catch (ex) { } } @@ -2325,30 +2231,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (common.validateString(command.title, 1, 512) == false) break; // Check title if (common.validateString(command.msg, 1, 4096) == false) break; // Check message for (i in command.nodeids) { - nodeid = command.nodeids[i]; - var powerActions = 0; - if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + // Check we have the rights to delete this device + if ((rights & MESHRIGHT_CHATNOTIFY) == 0) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_CHATNOTIFY) != 0) { - // Get this device - var agent = parent.wsagents[node._id]; - if (agent != null) { - // Send the power command - try { agent.send(JSON.stringify({ action: 'toast', title: command.title, msg: command.msg, sessionid: ws.sessionId, username: user.name, userid: user._id })); } catch (ex) { } - } - } - } - }); - } + // Get this device and send toast command + const agent = parent.wsagents[node._id]; + if (agent != null) { + try { agent.send(JSON.stringify({ action: 'toast', title: command.title, msg: command.msg, sessionid: ws.sessionId, username: user.name, userid: user._id })); } catch (ex) { } + } + }); } break; } @@ -2358,24 +2251,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain - // Get the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); } catch (ex) { } return; } - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if (visible == false) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if (parent.GetMeshRights(user, mesh) == 0) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); } catch (ex) { } return; } - - // Get network information about this node - db.Get('if' + command.nodeid, function (err, netinfos) { - if ((netinfos == null) || (netinfos.length != 1)) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); } catch (ex) { } return; } - var netinfo = netinfos[0]; - try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, updateTime: netinfo.updateTime, netif: netinfo.netif })); } catch (ex) { } - }); - } + // Get network information about this node + db.Get('if' + node._id, function (err, netinfos) { + if ((netinfos == null) || (netinfos.length != 1)) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: node._id, netif: null })); } catch (ex) { } return; } + var netinfo = netinfos[0]; + try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: node._id, updateTime: netinfo.updateTime, netif: netinfo.netif })); } catch (ex) { } + }); }); break; } @@ -2383,106 +2268,89 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use { // Argument validation if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid - if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain if ((command.userloc) && (command.userloc.length != 2) && (command.userloc.length != 0)) return; - // Change the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if ((rights & MESHRIGHT_MANAGECOMPUTERS) == 0) return; + var mesh = parent.meshes[node.meshid]; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return; + // Ready the node change event + var changes = [], event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id }; + change = 0; + event.msg = ': '; - // Ready the node change event - var changes = [], event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id }; - change = 0; - event.msg = ": "; + // If we are in WAN-only mode, host is not used + if ((args.wanonly == true) && (command.host)) { delete command.host; } - // If we are in WAN-only mode, host is not used - if ((args.wanonly == true) && (command.host)) { delete command.host; } - - // Look for a change - if (command.icon && (command.icon != node.icon)) { change = 1; node.icon = command.icon; changes.push('icon'); } - if (command.name && (command.name != node.name)) { change = 1; node.name = command.name; changes.push('name'); } - if (command.host && (command.host != node.host)) { change = 1; node.host = command.host; changes.push('host'); } - if (domain.geolocation && command.userloc && ((node.userloc == null) || (command.userloc[0] != node.userloc[0]) || (command.userloc[1] != node.userloc[1]))) { - change = 1; - if ((command.userloc.length == 0) && (node.userloc)) { - delete node.userloc; - changes.push('location removed'); - } else { - command.userloc.push((Math.floor((new Date()) / 1000))); - node.userloc = command.userloc.join(','); - changes.push('location'); - } + // Look for a change + if (command.icon && (command.icon != node.icon)) { change = 1; node.icon = command.icon; changes.push('icon'); } + if (command.name && (command.name != node.name)) { change = 1; node.name = command.name; changes.push('name'); } + if (command.host && (command.host != node.host)) { change = 1; node.host = command.host; changes.push('host'); } + if (domain.geolocation && command.userloc && ((node.userloc == null) || (command.userloc[0] != node.userloc[0]) || (command.userloc[1] != node.userloc[1]))) { + change = 1; + if ((command.userloc.length == 0) && (node.userloc)) { + delete node.userloc; + changes.push('location removed'); + } else { + command.userloc.push((Math.floor((new Date()) / 1000))); + node.userloc = command.userloc.join(','); + changes.push('location'); } - if (command.desc != null && (command.desc != node.desc)) { change = 1; node.desc = command.desc; changes.push('description'); } - if (command.intelamt != null) { - if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); } - if (command.intelamt.tls && (command.intelamt.tls != node.intelamt.tls)) { change = 1; node.intelamt.tls = command.intelamt.tls; changes.push('Intel AMT TLS'); } - } - if (command.tags) { // Node grouping tag, this is a array of strings that can't be empty and can't contain a comma - var ok = true, group2 = []; - if (common.validateString(command.tags, 0, 4096) == true) { command.tags = command.tags.split(','); } - for (var i in command.tags) { var tname = command.tags[i].trim(); if ((tname.length > 0) && (tname.length < 64) && (group2.indexOf(tname) == -1)) { group2.push(tname); } } - group2.sort(); - if (node.tags != group2) { node.tags = group2; change = 1; } - } else if ((command.tags === '') && node.tags) { delete node.tags; change = 1; } + } + if (command.desc != null && (command.desc != node.desc)) { change = 1; node.desc = command.desc; changes.push('description'); } + if (command.intelamt != null) { + if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); } + if (command.intelamt.tls && (command.intelamt.tls != node.intelamt.tls)) { change = 1; node.intelamt.tls = command.intelamt.tls; changes.push('Intel AMT TLS'); } + } + if (command.tags) { // Node grouping tag, this is a array of strings that can't be empty and can't contain a comma + var ok = true, group2 = []; + if (common.validateString(command.tags, 0, 4096) == true) { command.tags = command.tags.split(','); } + for (var i in command.tags) { var tname = command.tags[i].trim(); if ((tname.length > 0) && (tname.length < 64) && (group2.indexOf(tname) == -1)) { group2.push(tname); } } + group2.sort(); + if (node.tags != group2) { node.tags = group2; change = 1; } + } else if ((command.tags === '') && node.tags) { delete node.tags; change = 1; } - if (change == 1) { - // Save the node - db.Set(node); + if (change == 1) { + // Save the node + db.Set(node); - // 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(', '); - event.node = parent.CloneSafeNode(node); - 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); - } + // 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(', '); + event.node = parent.CloneSafeNode(node); + 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); } }); break; } case 'uploadagentcore': { - if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid if (common.validateString(command.type, 1, 40) == false) break; // Check path - // Change the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF))) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if (((parent.GetMeshRights(user, mesh) & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF)) { return; } - - if (command.type == 'default') { - // Send the default core to the agent - parent.parent.updateMeshCore(function () { parent.sendMeshAgentCore(user, domain, command.nodeid, 'default'); }); - } else if (command.type == 'clear') { - // Clear the mesh agent core on the mesh agent - parent.sendMeshAgentCore(user, domain, command.nodeid, 'clear'); - } else if (command.type == 'recovery') { - // Send the recovery core to the agent - parent.sendMeshAgentCore(user, domain, command.nodeid, 'recovery'); - } else if ((command.type == 'custom') && (common.validateString(command.path, 1, 2048) == true)) { - // Send a mesh agent core to the mesh agent - var file = parent.getServerFilePath(user, domain, command.path); - if (file != null) { - fs.readFile(file.fullpath, 'utf8', function (err, data) { - if (err != null) { - data = common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw) - parent.sendMeshAgentCore(user, domain, command.nodeid, 'custom', data); - } - }); - } + if (command.type == 'default') { + // Send the default core to the agent + parent.parent.updateMeshCore(function () { parent.sendMeshAgentCore(user, domain, node._id, 'default'); }); + } else if (command.type == 'clear') { + // Clear the mesh agent core on the mesh agent + parent.sendMeshAgentCore(user, domain, node._id, 'clear'); + } else if (command.type == 'recovery') { + // Send the recovery core to the agent + parent.sendMeshAgentCore(user, domain, node._id, 'recovery'); + } else if ((command.type == 'custom') && (common.validateString(command.path, 1, 2048) == true)) { + // Send a mesh agent core to the mesh agent + var file = parent.getServerFilePath(user, domain, command.path); + if (file != null) { + fs.readFile(file.fullpath, 'utf8', function (err, data) { + if (err != null) { + data = common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw) + parent.sendMeshAgentCore(user, domain, node._id, 'custom', data); + } + }); } } }); @@ -2490,23 +2358,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'agentdisconnect': { - if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid if (common.validateInt(command.disconnectMode) == false) return; // Check disconnect mode - // Change the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF))) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if (((parent.GetMeshRights(user, mesh) & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF)) return; - - // Force mesh agent disconnection - parent.forceMeshAgentDisconnect(user, domain, command.nodeid, command.disconnectMode); - } + // Force mesh agent disconnection + parent.forceMeshAgentDisconnect(user, domain, node._id, command.disconnectMode); }); break; } @@ -2552,7 +2411,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use mesh = parent.meshes[command.meshid]; if (mesh == null) { err = 'Unknown device group'; } // Check if the group exists else if (mesh.mtype != 2) { err = 'Invalid group type'; } // Check if this is the correct group type - else if (parent.GetMeshRights(user, mesh) == 0) { err = 'Not allowed'; } // Check if this user has rights to do this + else if (parent.IsMeshViewable(user, mesh) == false) { err = 'Not allowed'; } // Check if this user has rights to do this } } } catch (ex) { err = 'Validation exception: ' + ex; } @@ -2574,24 +2433,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use { // Argument validation if (common.validateString(command.msg, 1, 4096) == false) break; // Check event - if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid - var splitid = command.nodeid.split('/'); - if ((splitid.length != 3) || (splitid[1] != domain.id)) return; // Invalid domain, operation only valid for current domain - var idtype = splitid[0]; - if ((idtype != 'node')) return; - // Check if this user has rights on this id to set notes - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length == 1)) { - if (parent.GetMeshRights(user, nodes[0].meshid) != 0) { - // Add an event for this device - var targets = ['*', 'server-users', user._id, nodes[0].meshid]; - var event = { etype: 'node', userid: user._id, username: user.name, nodeid: nodes[0]._id, action: 'manual', msg: decodeURIComponent(command.msg), domain: domain.id }; - parent.parent.DispatchEvent(targets, obj, event); - } - } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if (rights == 0) return; + + // Add an event for this device + var targets = ['*', 'server-users', user._id, nodes[0].meshid]; + var event = { etype: 'node', userid: user._id, username: user.name, nodeid: nodes[0]._id, action: 'manual', msg: decodeURIComponent(command.msg), domain: domain.id }; + parent.parent.DispatchEvent(targets, obj, event); }); - break; } case 'setNotes': @@ -2604,16 +2455,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((idtype != 'user') && (idtype != 'mesh') && (idtype != 'node')) return; if (idtype == 'node') { - // Check if this user has rights on this id to set notes - db.Get(command.id, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???) - if ((nodes == null) || (nodes.length == 1)) { - if ((parent.GetMeshRights(user, nodes[0].meshid) & MESHRIGHT_SETNOTES) != 0) { - // Set the id's notes - if (common.validateString(command.notes, 1) == false) { - db.Remove('nt' + command.id); // Delete the note for this node - } else { - db.Set({ _id: 'nt' + command.id, type: 'note', value: command.notes }); // Set the note for this node - } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.id, function (node, rights, visible) { + if ((rights & MESHRIGHT_SETNOTES) != 0) { + // Set the id's notes + if (common.validateString(command.notes, 1) == false) { + db.Remove('nt' + node._id); // Delete the note for this node + } else { + db.Set({ _id: 'nt' + node._id, type: 'note', value: command.notes }); // Set the note for this node } } }); @@ -2893,44 +2742,26 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use case 'getClip': { if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid - // Get the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has "remote" rights to do this - var meshrights = parent.GetMeshRights(user, mesh); - if ((meshrights & MESHRIGHT_AGENTCONSOLE) == 0) return; - - // Ask for clipboard data from agent - var agent = parent.wsagents[node._id]; - if (agent != null) { try { agent.send(JSON.stringify({ action: 'getClip' })); } catch (ex) { } } - } + // Ask for clipboard data from agent + var agent = parent.wsagents[node._id]; + if (agent != null) { try { agent.send(JSON.stringify({ action: 'getClip' })); } catch (ex) { } } }); break; } case 'setClip': { - if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid if (common.validateString(command.data, 1, 65535) == false) break; // Check - // Get the device - db.Get(command.nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has "remote" rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_AGENTCONSOLE) == 0) return; - - // Send clipboard data to the agent - var agent = parent.wsagents[node._id]; - if (agent != null) { try { agent.send(JSON.stringify({ action: 'setClip', data: command.data })); } catch (ex) { } } - } + // Send clipboard data to the agent + var agent = parent.wsagents[node._id]; + if (agent != null) { try { agent.send(JSON.stringify({ action: 'setClip', data: command.data })); } catch (ex) { } } }); break; } @@ -2951,25 +2782,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((idtype != 'user') && (idtype != 'mesh') && (idtype != 'node')) return; if (idtype == 'node') { - // Get the device - db.Get(command.id, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.id, function (node, rights, visible) { + if (visible == false) return; - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if (parent.GetMeshRights(user, mesh) == 0) return; - - // Get the notes about this node - db.Get('nt' + command.id, function (err, notes) { - try { - if ((notes == null) || (notes.length != 1)) { ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: null })); return; } - ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: notes[0].value })); - } catch (ex) { } - }); - } + // Get the notes about this node + db.Get('nt' + command.id, function (err, notes) { + try { + if ((notes == null) || (notes.length != 1)) { ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: null })); return; } + ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: notes[0].value })); + } catch (ex) { } + }); }); } else if (idtype == 'mesh') { // Get the mesh for this device @@ -3037,6 +2860,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } case 'sendmqttmsg': { + if (parent.parent.mqttbroker == null) { err = 'MQTT not supported on this server'; }; // MQTT not available if (common.validateArray(command.nodeids, 1) == false) { err = 'Invalid nodeids'; }; // Check nodeid's if (common.validateString(command.topic, 1, 64) == false) { err = 'Invalid topic'; } // Check the topic if (common.validateString(command.msg, 1, 4096) == false) { err = 'Invalid msg'; } // Check the message @@ -3047,30 +2871,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } - // TODO: We can optimize this a lot. - // - We should get a full list of all MAC's to wake first. - // - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan. + // Send the MQTT message for (i in command.nodeids) { - nodeid = command.nodeids[i]; - var wakeActions = 0; - if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; - - // Get the mesh for this device - mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_WAKEDEVICE) != 0) { - // If this device is connected on MQTT, send a wake action. - if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, command.topic, command.msg); } - } - } - }); - } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + // If this device is connected on MQTT, send a wake action. + if (rights != 0) { parent.parent.mqttbroker.publish(node._id, command.topic, command.msg); } + }); } break; @@ -3083,43 +2890,33 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Handle any errors if (err != null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: err })); } catch (ex) { } } break; } - var nodeid = command.nodeid; - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: 'Invalid node id' })); } catch (ex) { } return; } } - var node = nodes[0]; + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + // Check if this user has rights to do this + if (rights == 0xFFFFFFFF) { + var token = parent.parent.mqttbroker.generateLogin(node.meshid, node._id); + var r = { action: 'getmqttlogin', responseid: command.responseid, nodeid: node._id, user: token.user, pass: token.pass }; + const serverName = parent.getWebServerName(domain); - // Get the device group for this node - var mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) == 0xFFFFFFFF)) { - var token = parent.parent.mqttbroker.generateLogin(mesh._id, node._id); - var r = { action: 'getmqttlogin', responseid: command.responseid, nodeid: node._id, user: token.user, pass: token.pass }; - const serverName = parent.getWebServerName(domain); - - // Add MPS URL - if (parent.parent.mpsserver != null) { - r.mpsCertHashSha384 = parent.parent.certificateOperations.getCertHash(parent.parent.mpsserver.certificates.mps.cert); - r.mpsCertHashSha1 = parent.parent.certificateOperations.getCertHashSha1(parent.parent.mpsserver.certificates.mps.cert); - r.mpsUrl = 'mqtts://' + serverName + ':' + ((args.mpsaliasport != null) ? args.mpsaliasport : args.mpsport) + '/'; - } - - // Add WS URL - var xdomain = (domain.dns == null) ? domain.id : ''; - if (xdomain != '') xdomain += "/"; - var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified - r.wsUrl = "ws" + (args.notls ? '' : 's') + "://" + serverName + ":" + httpsPort + "/" + xdomain + "mqtt.ashx"; - r.wsTrustedCert = parent.isTrustedCert(domain); - - try { ws.send(JSON.stringify(r)); } catch (ex) { } - } else { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: 'Unable to perform this operation' })); } catch (ex) { } } - } + // Add MPS URL + if (parent.parent.mpsserver != null) { + r.mpsCertHashSha384 = parent.parent.certificateOperations.getCertHash(parent.parent.mpsserver.certificates.mps.cert); + r.mpsCertHashSha1 = parent.parent.certificateOperations.getCertHashSha1(parent.parent.mpsserver.certificates.mps.cert); + r.mpsUrl = 'mqtts://' + serverName + ':' + ((args.mpsaliasport != null) ? args.mpsaliasport : args.mpsport) + '/'; } - }); - } + + // Add WS URL + var xdomain = (domain.dns == null) ? domain.id : ''; + if (xdomain != '') xdomain += '/'; + var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified + r.wsUrl = 'ws' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'mqtt.ashx'; + r.wsTrustedCert = parent.isTrustedCert(domain); + + try { ws.send(JSON.stringify(r)); } catch (ex) { } + } else { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: 'Unable to perform this operation' })); } catch (ex) { } } + } + }); break; } case 'amt': { @@ -3136,23 +2933,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } else if (command.mode == 3) { if (parent.parent.apfserver.apfConnections[command.nodeid] == null) break; } - var nodeid = command.nodeid; - if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain - // Get the device - db.Get(nodeid, function (err, nodes) { - if ((nodes == null) || (nodes.length != 1)) return; - var node = nodes[0]; - // Get the mesh for this device - var mesh = parent.meshes[node.meshid]; - if (mesh) { - // Check if this user has rights to do this - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_REMOTECONTROL) != 0) { // "Remote Control permission" - handleAmtCommand(command, node); - } - } - }); - } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return; + handleAmtCommand(command, node); + }); break; } case 'distributeCore': { @@ -3304,15 +3090,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Read all files recursively try { - files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2])); + files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2])); } catch (e) { // TODO: We may want to fake this file structure until it's needed. // Got an error, try to create all the folders and try again... try { fs.mkdirSync(parent.filespath); } catch (e) { } try { fs.mkdirSync(parent.path.join(parent.filespath, domainx)); } catch (e) { } - try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2])); } catch (e) { } - try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2] + "/Public")); } catch (e) { } - try { files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2])); } catch (e) { } + try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2])); } catch (e) { } + try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2] + '/Public')); } catch (e) { } + try { files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2])); } catch (e) { } } // Add files for each mesh // TODO: Get all meshes including groups!! @@ -3326,7 +3112,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Read all files recursively try { - files.filetree.f[mesh._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + "/mesh-" + meshsplit[2])); + files.filetree.f[mesh._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + '/mesh-' + meshsplit[2])); } catch (e) { files.filetree.f[mesh._id].f = {}; // Got an error, return empty folder. We will create the folder only when needed. } @@ -3338,7 +3124,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use try { ws.send(JSON.stringify(files)); } catch (ex) { } } - function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(//g, '>').replace(//g, '>').replace(/').replace(/\n/g, '').replace(/\t/g, '  '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; } // Split a string taking into account the quoats. Used for command line parsing @@ -3388,13 +3174,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use node.intelamt.tls, tlsoptions, parent.parent, cmd.mode); var amt = new Amt(wsman); switch (cmd.command) { - case "Get-GeneralSettings": { - amt.Get("AMT_GeneralSettings", function (obj, name, response, status) { + case 'Get-GeneralSettings': { + amt.Get('AMT_GeneralSettings', function (obj, name, response, status) { if (status == 200) { var resp = { action: 'amt', nodeid: cmd.nodeid, command: 'Get-GeneralSettings', value: response.Body } ws.send(JSON.stringify(resp)); } else { - ws.send(JSON.stringify({ "error": error })); + ws.send(JSON.stringify({ 'error': error })); } }); break; diff --git a/mpsserver.js b/mpsserver.js index 69a04c45..2935a598 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -11,7 +11,7 @@ /*jshint strict:false */ /*jshint -W097 */ /*jshint esversion: 6 */ -"use strict"; +'use strict'; // Construct a Intel AMT MPS server object module.exports.CreateMpsServer = function (parent, db, args, certificates) { @@ -24,9 +24,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { var tlsSessionStore = {}; // Store TLS session information for quick resume. var tlsSessionStoreCount = 0; // Number of cached TLS session information in store. const constants = (require('crypto').constants ? require('crypto').constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead. - const common = require("./common.js"); - const net = require("net"); - const tls = require("tls"); + const common = require('./common.js'); + const net = require('net'); + const tls = require('tls'); const MAX_IDLE = 90000; // 90 seconds max idle time, higher than the typical KEEP-ALIVE periode of 60 seconds if (obj.args.mpstlsoffload) { @@ -42,9 +42,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { obj.server.listen(args.mpsport, function () { console.log("MeshCentral Intel(R) AMT server running on " + certificates.AmtMpsName + ":" + args.mpsport + ((args.mpsaliasport != null) ? (", alias port " + args.mpsaliasport) : "") + "."); }).on("error", function (err) { console.error("ERROR: MeshCentral Intel(R) AMT server port " + args.mpsport + " is not available."); if (args.exactports) { process.exit(); } }); obj.server.on('tlsClientError', function (err, tlssocket) { if (args.mpsdebug) { var remoteAddress = tlssocket.remoteAddress; if (tlssocket.remoteFamily == 'IPv6') { remoteAddress = '[' + remoteAddress + ']'; } console.log('MPS:Invalid TLS connection from ' + remoteAddress + ':' + tlssocket.remotePort + '.'); } }); - obj.parent.updateServerState("mps-port", args.mpsport); - obj.parent.updateServerState("mps-name", certificates.AmtMpsName); - if (args.mpsaliasport != null) { obj.parent.updateServerState("mps-alias-port", args.mpsaliasport); } + obj.parent.updateServerState('mps-port', args.mpsport); + obj.parent.updateServerState('mps-name', certificates.AmtMpsName); + if (args.mpsaliasport != null) { obj.parent.updateServerState('mps-alias-port', args.mpsaliasport); } const APFProtocol = { UNKNOWN: 0, @@ -202,47 +202,47 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { function onConnection(socket) { connectionCount++; if (obj.args.mpstlsoffload) { - socket.tag = { first: true, clientCert: null, accumulator: "", activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 }; + socket.tag = { first: true, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 }; } else { - socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "", activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 }; + socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 }; } - socket.setEncoding("binary"); + socket.setEncoding('binary'); parent.debug('mps', "New CIRA connection"); // Setup the CIRA keep alive timer socket.setTimeout(MAX_IDLE); - socket.on("timeout", () => { ciraTimeoutCount++; parent.debug('mps', "CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } }); + socket.on('timeout', () => { ciraTimeoutCount++; parent.debug('mps', "CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } }); - socket.addListener("data", function (data) { - if (args.mpsdebug) { var buf = Buffer.from(data, "binary"); console.log("MPS <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes + socket.addListener('data', function (data) { + if (args.mpsdebug) { var buf = Buffer.from(data, 'binary'); console.log("MPS <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes socket.tag.accumulator += data; // Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port. if (socket.tag.first == true) { if (socket.tag.accumulator.length < 3) return; //if (!socket.tag.clientCert.subject) { console.log("MPS Connection, no client cert: " + socket.remoteAddress); socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 MPS server.\r\nNo client certificate given.'); socket.end(); return; } - if (socket.tag.accumulator.substring(0, 3) == "GET") { if (args.mpsdebug) { console.log("MPS Connection, HTTP GET detected: " + socket.remoteAddress); } socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\nMeshCentral2 MPS server.
Intel® AMT computers should connect here."); socket.end(); return; } + if (socket.tag.accumulator.substring(0, 3) == 'GET') { if (args.mpsdebug) { console.log("MPS Connection, HTTP GET detected: " + socket.remoteAddress); } socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\nMeshCentral2 MPS server.
Intel® AMT computers should connect here."); socket.end(); return; } // If the MQTT broker is active, look for inbound MQTT connections if (parent.mqttbroker != null) { - var chunk = Buffer.from(socket.tag.accumulator, "binary"); + var chunk = Buffer.from(socket.tag.accumulator, 'binary'); var packet_len = 0; if (chunk.readUInt8(0) == 16) { packet_len = getMQTTPacketLength(chunk); } if (chunk.readUInt8(0) == 16 && (socket.tag.accumulator.length < packet_len)) return; // Minimum MQTT detection // check if it is MQTT, need more initial packet to probe - if (chunk.readUInt8(0) == 16 && ((chunk.slice(4, 8).toString() === "MQTT") || (chunk.slice(5, 9).toString() === "MQTT") - || (chunk.slice(6, 10).toString() === "MQTT") || (chunk.slice(7, 11).toString() === "MQTT"))) { - parent.debug("mps", "MQTT connection detected."); + if (chunk.readUInt8(0) == 16 && ((chunk.slice(4, 8).toString() === 'MQTT') || (chunk.slice(5, 9).toString() === 'MQTT') + || (chunk.slice(6, 10).toString() === 'MQTT') || (chunk.slice(7, 11).toString() === 'MQTT'))) { + parent.debug('mps', "MQTT connection detected."); socket.removeAllListeners("data"); socket.removeAllListeners("close"); socket.setNoDelay(true); socket.serialtunnel = SerialTunnel(); socket.serialtunnel.xtransport = 'mps'; socket.serialtunnel.xip = socket.remoteAddress; - socket.on("data", function (b) { socket.serialtunnel.updateBuffer(Buffer.from(b, "binary")) }); - socket.serialtunnel.forwardwrite = function (b) { socket.write(b, "binary") } - socket.on("close", function () { socket.serialtunnel.emit("end"); }); + socket.on('data', function (b) { socket.serialtunnel.updateBuffer(Buffer.from(b, 'binary')) }); + socket.serialtunnel.forwardwrite = function (b) { socket.write(b, 'binary') } + socket.on('close', function () { socket.serialtunnel.emit('end'); }); // Pass socket wrapper to the MQTT broker parent.mqttbroker.handle(socket.serialtunnel); @@ -533,7 +533,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { var request = data.substring(5, 5 + requestLen); //var wantResponse = data.charCodeAt(5 + requestLen); - if (request == "tcpip-forward") { + if (request == 'tcpip-forward') { var addrLen = common.ReadInt(data, 6 + requestLen); if (len < 14 + requestLen + addrLen) return 0; var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen); @@ -545,7 +545,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { return 14 + requestLen + addrLen; } - if (request == "cancel-tcpip-forward") { + if (request == 'cancel-tcpip-forward') { var addrLen = common.ReadInt(data, 6 + requestLen); if (len < 14 + requestLen + addrLen) return 0; var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen); @@ -557,7 +557,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { return 14 + requestLen + addrLen; } - if (request == "udp-send-to@amt.intel.com") { + if (request == 'udp-send-to@amt.intel.com') { var addrLen = common.ReadInt(data, 6 + requestLen); if (len < 26 + requestLen + addrLen) return 0; var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen); @@ -748,14 +748,14 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { } } - socket.addListener("close", function () { + socket.addListener('close', function () { socketClosedCount++; parent.debug('mps', 'CIRA connection closed'); try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { } obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2); }); - socket.addListener("error", function () { + socket.addListener('error', function () { socketErrorCount++; //console.log("MPS Error: " + socket.remoteAddress); }); @@ -802,7 +802,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { */ function SendChannelOpen(socket, direct, channelid, windowsize, target, targetport, source, sourceport) { - var connectionType = ((direct == true) ? "direct-tcpip" : "forwarded-tcpip"); + var connectionType = ((direct == true) ? 'direct-tcpip' : 'forwarded-tcpip'); if ((target == null) || (target == null)) target = ''; // TODO: Reports of target being undefined that causes target.length to fail. This is a hack. Write(socket, String.fromCharCode(APFProtocol.CHANNEL_OPEN) + common.IntToStr(connectionType.length) + connectionType + common.IntToStr(channelid) + common.IntToStr(windowsize) + common.IntToStr(-1) + common.IntToStr(target.length) + target + common.IntToStr(targetport) + common.IntToStr(source.length) + source + common.IntToStr(sourceport)); } @@ -837,11 +837,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { function Write(socket, data) { if (args.mpsdebug) { // Print out sent bytes - var buf = Buffer.from(data, "binary"); + var buf = Buffer.from(data, 'binary'); console.log('MPS --> (' + buf.length + '):' + buf.toString('hex')); socket.write(buf); } else { - socket.write(Buffer.from(data, "binary")); + socket.write(Buffer.from(data, 'binary')); } } diff --git a/multiserver.js b/multiserver.js index 9a939984..cf758533 100644 --- a/multiserver.js +++ b/multiserver.js @@ -11,7 +11,7 @@ /*jshint strict:false */ /*jshint -W097 */ /*jshint esversion: 6 */ -"use strict"; +'use strict'; // Construct a Mesh Multi-Server object. This is used for MeshCentral-to-MeshCentral communication. module.exports.CreateMultiServer = function (parent, args) { @@ -552,14 +552,10 @@ module.exports.CreateMultiServer = function (parent, args) { if (msg.fromNodeid != null) { msg.nodeid = msg.fromNodeid; delete msg.fromNodeid; } var cmdstr = JSON.stringify(msg); for (userid in obj.parent.webserver.wssessions) { // Find all connected users for this mesh and send the message - var user = obj.parent.webserver.users[userid]; - if (user) { - var rights = user.links[msg.meshid]; - if (rights != null) { // TODO: Look at what rights are needed for message routing - var sessions = obj.parent.webserver.wssessions[userid]; - // Send the message to all users on this server - for (i in sessions) { sessions[i].send(cmdstr); } - } + if (parent.webserver.GetMeshRights(userid, msg.meshid) != 0) { // TODO: Look at what rights are needed for message routing + var sessions = obj.parent.webserver.wssessions[userid]; + // Send the message to all users on this server + for (i in sessions) { sessions[i].send(cmdstr); } } } } diff --git a/package.json b/package.json index f0ca0343..4a175977 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.4.6-p", + "version": "0.4.6-q", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/images/icons16.png b/public/images/icons16.png index d670429468a8a1fc57bdbce89b138f0f4035dd2f..a1a0a1c958753a89447f8dd4e61c80e8123fc4fe 100644 GIT binary patch literal 4062 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 literal 2201 zcmV;K2xj+*P)AHIP000PJNklN3>{jOgX z>@G$|hGA-L5z*ReL~Dx?Mxz1E%}pEzLnE4+^o)oGw70i&BC534P+HmG5EZ%>)HHQG zhWbXsVCcj$jr<{ zc6K%j3kx8Z%b`>jL8U5T11d$MzMlIw0sJHHJQ4K9_QwdZk-z6aB=-89a|oLVjs|n( zN-6&HCGhY6V%mNQ@w$|?Ei~El7C;aRAbhVH!uPu%Ja-qLNV^dbXTjl%{Wx&p2HZn# zK+gmqL2Lr}g^j`E@E~?EcpS3guocYTb?BzpzRkPOsQ}IFJ`pWdO(Lsg5;>)lh?d?) zSn?=V{vjN#rY@%fs8lKpkBo98>Nnv-&7YY+!mm}TEB`+NELxlk;Rk96D~u3cya8FU z3E2hh$W^wXP~D2yY%}x?bx3CI-wgO@jW<`+Jz(R zx}l+#mnNG4ZXfhvgIAjsrfKZ4+L`y5zjj9x6Tm#H0P5O%$Sj^@Lfpa87z;l5q2t{wyZ0~jA0!^HTw9q!z|4NISe_o2QN^XPM$ znhdC`t3ySl2BoEH6cs5MM}^4E&1Jl1At50Vm6esO?O{0-sKcK&xZvo~U?xBdva+)9 z`WrGVUY5a15GzG5RKWe;>8a@%Vkt_q`m%xohcR_^ zdbU1Xh5T~yyr7Vma7!^1YkQ8t&`iZBM}seB3!;K=j&)zRyIzY zIDv_Y2_7rtR3^aXu7D8jKD4wn&0ukuCqU{fmABx50NXBSo4k%s~E8_F_2y5V)b3L_V*cn{<<0zGn)Xup@Y~TYJpc! z8+QD?9$Vk9o>Ks6&Szo<+_Gf=7hnWApXEA?@%Im6v$7iP<_^r~*ZHq{n9ZHIrqzLB z=@|n91AND2>A%THS3$-mf>fG=)YLRK>l4^^`cp(lNAs<8cz8G>B2FVQF=<)=g+jrI zZ(%_)E`Usyk7d6|!t#~L_~w!%2upIY_?I)MRpY;MCE*B-pEPLJB!YMw3hkc$cF zSh=+UE7q0cr|ZkHg0OCeeFV#1R)At=6Ts_OA3XliiGZ_ac=*@gjeTWv3XqzXA(kC6 z1FSw}g);%vrJr*FIy#4DML<9x-qrjX`+U54CQ$6u)D&OfyL&9?AGpaa31l?3vMQm6 zPFIU6mKo*cS9vDn7oX~!s>bf9=LwM#4vk?r;E=ggfh%L%5 zmN8U9SbmvjKt{&&phChW_}NAso?k7SH^NSzpH%?QquuyRKpT$5v|;y$8vN0-XifoA z*o?E0O+xT&VE)aaTS#VY&IF*6G9Ll{7WG%S{qx&!b#>!06ib_yQ>Q`@7#PU$jc+Y- zi0?l89sKwwOT~UvhA2Di1h5^pnho{`uKM~~1|0_xPoNB-Kc_*&#--w9XcR&|mf%!a zG)K^hNE|i+FzN58*2DwX=k` zqxR#a)hq4#asg-;L|Y@?g=+{AAA)2F z8U!ATK*^N~yJyim%oKsX13h@~!0vkxwLkiYHT!f*$2mPay=pMR*!Q1y3rm)-Rh#dyU zrf_ro9(r$0;KtZpT<;qK#m;;d9SCg#Op{*4tyWtlia_nu&)I-}_sUuj*8KieJoMLo zEy?EsJnaJt3zeKms{2m@iR4qZvlyQBB;_I(fD@9k%6jSaSI`}+$` b_@nqAu#itV(vp$o00000NkvXXu0mjfk@_Uq diff --git a/public/images/icons256-7-1.png b/public/images/icons256-7-1.png new file mode 100644 index 0000000000000000000000000000000000000000..efeaf01641a3d93e12e58103e2ed3700ae7b84a9 GIT binary patch literal 47554 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

2K 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 A1ONa4 literal 0 HcmV?d00001 diff --git a/public/images/icons50.png b/public/images/icons50.png index ca16c28c74531cdc5e2ba273e79ad61c472d22d9..9da4f723d603d511e3a973cdf604b8bdced56bd6 100644 GIT binary patch literal 29091 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 diff --git a/public/images/icons64.png b/public/images/icons64.png index d8d25cebabfd4c1401a644dc70b5c7897ffe068b..261d43cacdb32a19525c31ea0633d203ba3e2b48 100644 GIT binary patch literal 47417 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≦@Jmn6k~$g; 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 i|HfS&sf7)yS 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

S&A)zqZ21-`eBj?sjPRy%R+c_Sn290L6u|JlMi3 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 diff --git a/public/styles/style.css b/public/styles/style.css index 75d4b26b..83d28311 100644 --- a/public/styles/style.css +++ b/public/styles/style.css @@ -1155,6 +1155,14 @@ a { border: none; } +.i7 { + background: url(../images/icons50.png) -300px 0px; + height: 50px; + width: 50px; + cursor: pointer; + border: none; +} + .j1 { background: url(../images/icons16.png) 0px 0px; height: 16px; @@ -1203,6 +1211,14 @@ a { border: none; } +.j7 { + background: url(../images/icons16.png) -96px 0px; + height: 16px; + width: 16px; + cursor: pointer; + border: none; +} + .relayIcon16 { background: url(../images/icon-relay.png); height: 16px; @@ -1339,7 +1355,7 @@ a { float: left; } -.si0 { +.si1 { background: url(../images/icons16.png) 0px 0px; height: 16px; width: 16px; @@ -1347,7 +1363,7 @@ a { float: left; } -.si1 { +.si2 { background: url(../images/icons16.png) -16px 0px; height: 16px; width: 16px; @@ -1355,7 +1371,7 @@ a { float: left; } -.si2 { +.si3 { background: url(../images/icons16.png) -32px 0px; height: 16px; width: 16px; @@ -1363,7 +1379,7 @@ a { float: left; } -.si3 { +.si4 { background: url(../images/icons16.png) -48px 0px; height: 16px; width: 16px; @@ -1371,7 +1387,7 @@ a { float: left; } -.si4 { +.si5 { background: url(../images/icons16.png) -64px 0px; height: 16px; width: 16px; @@ -1379,7 +1395,7 @@ a { float: left; } -.si5 { +.si6 { background: url(../images/icons16.png) -80px 0px; height: 16px; width: 16px; @@ -1387,6 +1403,14 @@ a { float: left; } +.si7 { + background: url(../images/icons16.png) -96px 0px; + height: 16px; + width: 16px; + border: none; + float: left; +} + .mi { background: url(../images/meshicon50.png) 0px 0px; height: 50px; diff --git a/translate/translate.json b/translate/translate.json index 9610c1b2..116266a3 100644 --- a/translate/translate.json +++ b/translate/translate.json @@ -8,8 +8,7 @@ "nl": "0", "xloc": [ "default.handlebars->container->masthead->7->notificationCount", - "default-mobile.handlebars->9->229", - { "$ref": "#" } + "default-mobile.handlebars->9->229" ] }, { @@ -5610,7 +5609,7 @@ { "en": "free", "fr": "libre", - "pt": "Livre", + "pt": "livre", "ja": "無料", "cs": "volné", "nl": "vrij", diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index 70e05bcc..74f56512 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -1327,7 +1327,7 @@ count++; // Mesh rights - var meshrights = meshes[i].links[userinfo._id].rights; + var meshrights = GetMeshRights(meshes[i]); var rights = "Partial Rights"; if (meshrights == 0xFFFFFFFF) rights = "Full Administrator"; else if (meshrights == 0) rights = "No Rights"; @@ -1576,8 +1576,7 @@ if (desktop && !xxdialogMode && xxcurrentView == 10) { // Check what keys we are allows to send if (currentNode != null) { - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentNode.meshid); var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0))); if (inputAllowed == false) return false; var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0))); @@ -1594,8 +1593,7 @@ if (desktop && !xxdialogMode && xxcurrentView == 10) { // Check what keys we are allows to send if (currentNode != null) { - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentNode.meshid); var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0))); if (inputAllowed == false) return false; var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0))); @@ -1612,8 +1610,7 @@ if (desktop && !xxdialogMode && xxcurrentView == 10) { // Check what keys we are allows to send if (currentNode != null) { - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentNode.meshid); var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0))); if (inputAllowed == false) return false; var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0))); @@ -1655,9 +1652,7 @@ // Go thru the list of nodes and display them for (var i in nodes) { if (nodes[i].v == false) continue; - var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links[userinfo._id]; - if (meshlinks == null) continue; - var meshrights = meshlinks.rights; + //var meshrights = GetNodeRights(nodes[i]); if (sort == 0) { // Mesh header @@ -1668,7 +1663,7 @@ if (meshes[nodes[i].meshid].mtype == 1) { extra = '' + ", Intel® AMT only" + ''; } if (current != null) { if (c == 2) { r += '

'; } if (r != '') { r += ''; } } r += '
'; - //r += getMeshActions(mesh2, meshrights); + //r += getMeshActions(meshes[nodes[i].meshid], meshrights); r += '' + EscapeHtml(meshes[nodes[i].meshid].name) + '' + extra + '
'; current = nodes[i].meshid; displayedMeshes[current] = 1; @@ -1726,20 +1721,17 @@ // Display all empty meshes, we need to do this because users can add devices to these at any time. if (sort == 0) { for (var i in meshes) { - var mesh = meshes[i], meshlink = mesh.links[userinfo._id]; - if (meshlink != null) { - var meshrights = meshlink.rights; - if (displayedMeshes[mesh._id] == null) { - if ((current != '') && (r != '')) { r += ''; } - r += '
'; - //r += getMeshActions(mesh, meshrights); - r += '' + EscapeHtml(mesh.name) + '
'; - if (mesh.mtype == 1) { r += '
' + "No Intel® AMT devices in this group"; } - if (mesh.mtype == 2) { r += '
' + "No devices in this group"; } - r += '.
'; - current = mesh._id; - count++; - } + var mesh = meshes[i]; + if (IsMeshViewable(mesh)) { + if ((current != '') && (r != '')) { r += ''; } + r += '
'; + //r += getMeshActions(mesh, meshrights); + r += '' + EscapeHtml(mesh.name) + '
'; + if (mesh.mtype == 1) { r += '
' + "No Intel® AMT devices in this group"; } + if (mesh.mtype == 2) { r += '
' + "No devices in this group"; } + r += '.
'; + current = mesh._id; + count++; } } } @@ -1813,11 +1805,6 @@ gotoDevice(nodeid, xxcurrentView, true); } - function getNodeRights(nodeid) { - var node = getNodeFromId(nodeid), mesh = meshes[node.meshid]; - return mesh.links[userinfo._id].rights; - } - var currentDevicePanel = 0; var currentNode; var powerTimelineNode = null; @@ -1837,7 +1824,7 @@ if (node == null) { goBack(); return; } var mesh = meshes[node.meshid]; if (mesh == null) { goBack(); return; } - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(mesh); if (!currentNode || currentNode._id != node._id || refresh == true) { currentNode = node; @@ -2008,8 +1995,7 @@ } function setupDeviceMenu(op, obj) { - var meshrights = 0; - if (currentNode) { meshrights = meshes[currentNode.meshid].links[userinfo._id].rights; } + var meshrights = GetNodeRights(currentNode); if (op != null) { currentDevicePanel = op; } QV('p10general', currentDevicePanel == 0); QV('p10desktop', currentDevicePanel == 1); // Show if we have remote control rights or desktop view only rights @@ -2027,7 +2013,7 @@ function deviceActionFunction() { if (xxdialogMode) return; - var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights; + var meshrights = GetNodeRights(currentNode); var x = "Select an operation to perform on this device." + '

'; var y = ''); x += addHtmlValue("Password", ''); @@ -2166,9 +2152,8 @@ function p10showiconselector() { if (xxdialogMode) return; - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; - if ((meshrights & 4) == 0) return; + var rights = GetNodeRights(currentNode); + if ((rights & 4) == 0) return; var x = '
'; x += '
'; @@ -2245,7 +2230,7 @@ var mesh = meshes[currentNode.meshid]; var deskState = 0; if (desktop != null) { deskState = desktop.State; } - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetNodeRights(currentNode); // Show the right buttons QV('disconnectbutton1', (deskState != 0)); @@ -3096,7 +3081,7 @@ if (currentMesh == null) return; QH('p20meshName', EscapeHtml(currentMesh.name)); var meshtype = format("Unknown #{0}", currentMesh.mtype); - var meshrights = currentMesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentMesh); if (currentMesh.mtype == 1) meshtype = "Intel® AMT only, no agent"; if (currentMesh.mtype == 2) meshtype = "Managed using a software agent"; @@ -3229,7 +3214,7 @@ } function p20validateAddMeshUserDialog() { - var meshrights = currentMesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentMesh); var nc = !Q('p20fulladmin').checked; QE('p20fulladmin', meshrights == 0xFFFFFFFF); QE('p20editmesh', nc && (meshrights == 0xFFFFFFFF)); @@ -3278,7 +3263,7 @@ function p20viewuser(userid) { if (xxdialogMode) return; userid = decodeURIComponent(userid); - var r = [], cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights; + var r = [], cmeshrights = GetMeshRights(currentMesh), meshrights = GetMeshRights(currentMesh, userid); if (meshrights == 0xFFFFFFFF) r.push("Full Administrator"); else { if ((meshrights & 1) != 0) r.push("Edit Device Group"); if ((meshrights & 2) != 0) r.push("Manage Device Group Users"); @@ -3361,6 +3346,49 @@ if (((b & 8) || x) && f) f(x, t); } + // + // Access Control Functions + // These must match server + // + + // Get the right of a user on a given device group + function GetMeshRights(mesh, user) { + if (mesh == null) { return 0; } + if (user == null) { user = userinfo._id; } + if (typeof mesh == 'string') { mesh = meshes[mesh] } + if ((mesh == null) || (mesh.links == null)) { return 0; } + var rights = mesh.links[user]; + if (rights == null) { return 0; } + return rights.rights; + } + + // Returns true if the user can view the given device group + function IsMeshViewable(mesh, user) { + if (mesh == null) { return 0; } + if (user == null) { user = userinfo._id; } + if (typeof mesh == 'string') { mesh = meshes[mesh] } + if ((mesh == null) || (mesh.links == null)) { return false; } + var rights = mesh.links[user]; + if (rights == null) { return false; } + return true; + } + + // Return the user rights for a given node + function GetNodeRights(node, user) { + if (node == null) { return 0; } + if (user == null) { user = userinfo._id; } + if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } + var mesh = meshes[node.meshid]; + if ((mesh == null) || (mesh.links == null)) { return 0; } + var meshlinks = mesh.links[user]; + if (meshlinks == null) { return 0; } + return meshlinks.rights; + } + + // + // Generic Methods + // + function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } } function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } } function center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + 'px'); deskAdjust(); deskAdjust(); /*drawDeviceTimeline();*/ } diff --git a/views/default.handlebars b/views/default.handlebars index 01c98e38..c8341864 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2587,8 +2587,7 @@ if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) { // Check what keys we are allows to send if (currentNode != null) { - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentNode.meshid); var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0))); if (inputAllowed == false) return false; var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0))); @@ -2647,8 +2646,7 @@ if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) { // Check what keys we are allows to send if (currentNode != null) { - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentNode.meshid); var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0))); if (inputAllowed == false) return false; var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0))); @@ -2682,8 +2680,7 @@ if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) { // Check what keys we are allows to send if (currentNode != null) { - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentNode.meshid); var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0))); if (inputAllowed == false) return false; var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0))); @@ -2783,10 +2780,9 @@ for (var i in nodes) { var node = nodes[i]; if (node.v == false) continue; - var mesh2 = meshes[node.meshid], meshlinks = mesh2.links[userinfo._id]; - if (meshlinks == null) continue; - var meshrights = meshlinks.rights; + var mesh2 = meshes[node.meshid]; if ((view == 3) && (mesh2.mtype == 1)) continue; + var meshrights = GetNodeRights(node); if (sort == 0) { // Mesh header if (node.meshid != current) { @@ -2948,37 +2944,34 @@ if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) { var deviceHeaderId2 = deviceHeaderId; for (var i in meshes) { - var mesh = meshes[i], meshlink = mesh.links[userinfo._id]; - if (meshlink != null) { - var meshrights = meshlink.rights; - if (displayedMeshes[mesh._id] == null) { - if ((current != '') && (r != '')) { r += '
'; } - r += '
'; + var mesh = meshes[i], meshrights = GetMeshRights(mesh); + if (displayedMeshes[mesh._id] == null) { + if ((current != '') && (r != '')) { r += '
'; } + r += ''; - if (mesh.mtype == 1) { - r += ''; - r += ''; // End collapsing area - - current = mesh._id; - count++; + r += '' + EscapeHtml(mesh.name) + ''; + r += getMeshActions(mesh, meshrights); + r += ''; + if (mesh.mtype == 1) { + r += ''; + r += ''; // End collapsing area + + current = mesh._id; + count++; } } } @@ -3107,8 +3100,8 @@ function toggleKvmDevice(node) { if (typeof node == 'string') { node = getNodeFromId(node); } // Convert nodeid to node if needed - var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights; - if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights + var rights = GetNodeRights(node); + if ((rights & 8) || (rights & 256)) { // Requires remote control rights or desktop view only rights //var conn = 0; //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT) if (node.conn & 1) { connectMultiDesktop(node, 1); } @@ -3133,8 +3126,8 @@ for (var i in nodes) { var node = nodes[i], nodeid = nodes[i]._id; if ((multiDesktop[nodeid] == null) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodeid) >= 0))) { - var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights; - if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights + var rights = GetNodeRights(node); + if ((rights & 8) || (rights & 256)) { // Requires remote control rights or desktop view only rights //var conn = 0; //if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT) if ((node.conn & 1) && (node.v == true)) { count++; } @@ -3646,9 +3639,8 @@ // Display the "Uninstall Agent" option if allowed and we selected connected devices. for (var i in nodeids) { var node = getNodeFromId(nodeids[i]); - var mesh = meshes[node.meshid]; - var meshrights = mesh.links[userinfo._id].rights; - if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += ''; break; } + var rights = GetNodeRights(node); + if (((node.conn & 1) != 0) && ((rights & 32768) != 0)) { addedOptions += ''; break; } } var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '

'; @@ -3790,19 +3782,18 @@ var nodeid = contextelement.children[1].attributes.onclick.value; var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18)); var mesh = meshes[node.meshid]; - var meshlinks = mesh.links[userinfo._id]; - var meshrights = meshlinks.rights; - var consoleRights = ((meshrights & 16) != 0); + var rights = GetNodeRights(node); + var consoleRights = ((rights & 16) != 0); // Check if we have terminal and file access - var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0)); - var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0)); + var terminalAccess = ((rights == 0xFFFFFFFF) || ((rights & 512) == 0)); + var fileAccess = ((rights == 0xFFFFFFFF) || ((rights & 1024) == 0)); - QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((meshrights & 8) || (meshrights & 256))); - QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess); - QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess); - QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8)); - QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8)); + QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((rights & 8) || (rights & 256))); + QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (rights & 8) && terminalAccess); + QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (rights & 8) && fileAccess); + QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (rights & 8)); + QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (rights & 8)); } return haltEvent(event); @@ -4488,11 +4479,6 @@ gotoDevice(nodeid, xxcurrentView, true); } - function getNodeRights(nodeid) { - var node = getNodeFromId(nodeid), mesh = meshes[node.meshid]; - return mesh.links[userinfo._id].rights; - } - var currentNode; var powerTimelineNode = null; var powerTimelineReq = null; @@ -4515,7 +4501,7 @@ //disconnectAllKvmFunction(); var node = getNodeFromId(nodeid); var mesh = meshes[node.meshid]; - var meshrights = mesh.links[userinfo._id].rights; + var meshrights = GetNodeRights(node); if (!currentNode || currentNode._id != node._id || refresh == true) { currentNode = node; @@ -4857,13 +4843,13 @@ function deviceActionFunction() { if (xxdialogMode) return; - var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights; + var rights = GetNodeRights(currentNode); var x = "Select an operation to perform on this device." + '

'; var y = ''; x += addHtmlValue("Operation", y); setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x); @@ -4975,7 +4961,7 @@ function editDeviceAmtSettings(nodeid, func, arg) { if (xxdialogMode) return; - var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid); + var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = GetNodeRights(node); if ((meshrights & 4) == 0) return; x += addHtmlValue("Username", ''); x += addHtmlValue("Password", ''); @@ -5049,7 +5035,7 @@ // List all available alternative groups var y = ''; @@ -5195,17 +5181,16 @@ function p10showiconselector() { if (xxdialogMode) return; - var mesh = meshes[currentNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; - if ((meshrights & 4) == 0) return; + if ((GetNodeRights(currentNode) & 4) == 0) return; - var x = '
'; + var x = '
'; x += '
'; x += '
'; x += '
'; x += '
'; x += '
'; - x += '


'; + x += '
'; + x += '


'; setDialogMode(2, "Icon Selection", 0, null, x); QV('id_dialogclose', true); } @@ -5292,14 +5277,14 @@ var mesh = meshes[currentNode.meshid]; var deskState = 0; if (desktop != null) { deskState = desktop.State; } - var meshrights = mesh.links[userinfo._id].rights; + var rights = GetNodeRights(currentNode); // Show the right buttons QV('disconnectbutton1span', (deskState != 0)); - QV('connectbutton1span', (deskState == 0) && ((meshrights & 8) || (meshrights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1)); + QV('connectbutton1span', (deskState == 0) && ((rights & 8) || (rights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1)); QV('connectbutton1hspan', (deskState == 0) && - (meshrights & 8) && + (rights & 8) && ((mesh.mtype == 1) || ((currentNode.intelamt != null) && (currentNode.intelamt.state == 2) && @@ -5314,7 +5299,7 @@ QV('d7meshkvm', (webRtcDesktop) || ((mesh.mtype == 2) && (currentNode.agent.caps & 1) && ((deskState == false) || (desktop.contype == 1)))); // Enable buttons - var inputAllowed = (meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) == 0)); + var inputAllowed = (rights == 0xFFFFFFFF) || (((rights & 8) != 0) && ((rights & 256) == 0) && ((rights & 4096) == 0)); var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop QE('connectbutton1', online); var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal @@ -5330,8 +5315,8 @@ QE('deskkeys', deskState == 3); // Display this only if we have Chat & Notify permissions - QV('DeskChatButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online); - QV('DeskNotifyButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online); + QV('DeskChatButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online); + QV('DeskNotifyButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online); QV('DeskToolsButton', (inputAllowed) && (mesh.mtype == 2) && online); QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online); @@ -5339,7 +5324,7 @@ QV('DeskControlSpan', inputAllowed) QV('deskActionsBtn', (browserfullscreen == false)); QV('deskActionsSettings', (browserfullscreen == false)); - if (meshrights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; } + if (rights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; } if (online == false) QV('DeskTools', false); } @@ -6966,8 +6951,8 @@ consoleNode = currentNode; var mesh = meshes[consoleNode.meshid]; - var meshrights = mesh.links[userinfo._id].rights; - if ((meshrights & 16) != 0) { + var rights = GetNodeRights(currentNode); + if ((rights & 16) != 0) { if (consoleNode.consoleText == null) { consoleNode.consoleText = ''; } if (samenode == false) { QH('p15agentConsoleText', consoleNode.consoleText); @@ -7443,8 +7428,7 @@ count++; // Mesh rights - var meshrights = 0; - if (meshes[i].links[userinfo._id]) { meshrights = meshes[i].links[userinfo._id].rights; } + var meshrights = GetMeshRights(meshes[i]); var rights = "Partial Rights"; if (meshrights == 0xFFFFFFFF) rights = "Full Administrator"; else if (meshrights == 0) rights = "No Rights"; @@ -7511,8 +7495,7 @@ if (currentMesh == null) return; QH('p20meshName', EscapeHtml(currentMesh.name)); var meshtype = format("Unknown #{0}", currentMesh.mtype); - var meshrights = 0; - try { meshrights = currentMesh.links[userinfo._id].rights; } catch (ex) { } + var meshrights = GetMeshRights(currentMesh); if (currentMesh.mtype == 1) meshtype = "Intel® AMT only, no agent"; if (currentMesh.mtype == 2) meshtype = "Managed using a software agent"; @@ -7580,10 +7563,9 @@ if (meshrights & 1) { x += '
'; } x += '

'; - var currentMeshLinks = currentMesh.links[userinfo._id]; - if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += ' ' + "Add Users" + ''; } + if (meshrights & 2) { x += ' ' + "Add Users" + ''; } - if ((meshrights & 4) != 0) { + if (meshrights & 4) { if (currentMesh.mtype == 1) { x += ' ' + "Install CIRA" + ''; x += ' ' + "Install local" + ''; @@ -7838,7 +7820,7 @@ Q('dp20username').focus(); } else { setDialogMode(2, "Edit User Device Group Permissions", 7, p20showAddMeshUserDialogEx, x, userid); - var cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights; + var cmeshrights = GetMeshRights(currentMesh), meshrights = GetMeshRights(currentMesh, userid); if (meshrights == 0xFFFFFFFF) { Q('p20fulladmin').checked = true; } else { @@ -7877,7 +7859,7 @@ } function p20validateAddMeshUserDialog() { - var meshrights = currentMesh.links[userinfo._id].rights; + var meshrights = GetMeshRights(currentMesh); var ok = true; if (Q('dp20username')) { var xusers = Q('dp20username').value.split(','); @@ -7964,7 +7946,7 @@ function p20viewuser(userid) { if (xxdialogMode) return; var xuserid = decodeURIComponent(userid); - var cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[xuserid].rights; + var cmeshrights = GetMeshRights(currentMesh), meshrights = GetMeshRights(currentMesh, xuserid); if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) { p20showAddMeshUserDialog(userid); } else { @@ -10063,7 +10045,49 @@ if (pname == null) { Q('p43iframe').src = ''; } else { QH('p43title', title); Q('p43iframe').src = '/pluginadmin.ashx?pin=' + pname; go(43); } } + // + // Access Control Functions + // These must match server + // + + // Get the right of a user on a given device group + function GetMeshRights(mesh, user) { + if (mesh == null) { return 0; } + if (user == null) { user = userinfo._id; } + if (typeof mesh == 'string') { mesh = meshes[mesh] } + if ((mesh == null) || (mesh.links == null)) { return 0; } + var rights = mesh.links[user]; + if (rights == null) { return 0; } + return rights.rights; + } + + // Returns true if the user can view the given device group + function IsMeshViewable(mesh, user) { + if (mesh == null) { return 0; } + if (user == null) { user = userinfo._id; } + if (typeof mesh == 'string') { mesh = meshes[mesh] } + if ((mesh == null) || (mesh.links == null)) { return false; } + var rights = mesh.links[user]; + if (rights == null) { return false; } + return true; + } + + // Return the user rights for a given node + function GetNodeRights(node, user) { + if (node == null) { return 0; } + if (user == null) { user = userinfo._id; } + if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } + var mesh = meshes[node.meshid]; + if ((mesh == null) || (mesh.links == null)) { return 0; } + var meshlinks = mesh.links[user]; + if (meshlinks == null) { return 0; } + return meshlinks.rights; + } + + // // Generic methods + // + function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); } function putstore(name, val) { try { diff --git a/webserver.js b/webserver.js index be1822c1..6a08e054 100644 --- a/webserver.js +++ b/webserver.js @@ -2065,7 +2065,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((splitpath.length < 3) || (splitpath[0] != 'user' && splitpath[0] != 'mesh') || (splitpath[1] != domain.id)) return null; // Basic validation var objid = splitpath[0] + '/' + splitpath[1] + '/' + splitpath[2]; if (splitpath[0] == 'user' && (objid != user._id)) return null; // User validation, only self allowed - if (splitpath[0] == 'mesh') { var link = user.links[objid]; if ((link == null) || (link.rights == null) || ((link.rights & 32) == 0)) { return null; } } // Check mesh server file rights + if (splitpath[0] == 'mesh') { if ((obj.GetMeshRights(user, objid) & 32) == 0) { return null; } } // Check mesh server file rights if (splitpath[1] != '') { serverpath += '-' + splitpath[1]; } // Add the domain if needed serverpath += ('/' + splitpath[0] + '-' + splitpath[2]); for (var i = 3; i < splitpath.length; i++) { if (obj.common.IsFilenameValid(splitpath[i]) == true) { serverpath += '/' + splitpath[i]; filename = splitpath[i]; } else { return null; } } // Check that each folder is correct @@ -2265,8 +2265,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (!node.intelamt) { console.log('ERR: Not AMT node'); try { ws.close(); } catch (e) { } return; } // Disconnect websocket // Check if this user has permission to manage this computer - var meshlinks = user.links[node.meshid]; - if ((!meshlinks) || (!meshlinks.rights) || ((meshlinks.rights & MESHRIGHT_REMOTECONTROL) == 0)) { console.log('ERR: Access denied (2)'); try { ws.close(); } catch (e) { } return; } + if ((obj.GetMeshRights(user, node.meshid) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { ws.close(); } catch (e) { } return; } // Check what connectivity is available for this node var state = parent.GetConnectivityState(req.query.host); @@ -2998,9 +2997,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // If required, check if this user has rights to do this if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true))) { - var user = obj.users[req.session.userid]; - if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; } - if (domain.id != mesh.domain) { res.sendStatus(401); return; } + if ((domain.id != mesh.domain) || ((obj.GetMeshRights(req.session.userid, mesh) & 1) == 0)) { res.sendStatus(401); return; } } var meshidhex = Buffer.from(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase(); @@ -3168,9 +3165,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // If required, check if this user has rights to do this if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true))) { - var user = obj.users[req.session.userid]; - if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; } - if (domain.id != mesh.domain) { res.sendStatus(401); return; } + if ((domain.id != mesh.domain) || ((obj.GetMeshRights(req.session.userid, mesh) & 1) == 0)) { res.sendStatus(401); return; } } var meshidhex = Buffer.from(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase(); @@ -3257,9 +3252,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // If needed, check if this user has rights to do this if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true))) { - var user = obj.users[req.session.userid]; - if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; } - if (domain.id != mesh.domain) { res.sendStatus(401); return; } + if ((domain.id != mesh.domain) || ((obj.GetMeshRights(req.session.userid, mesh) & 1) == 0)) { res.sendStatus(401); return; } } var meshidhex = Buffer.from(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase(); @@ -3297,9 +3290,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var node = docs[0]; // Check if we have right to this node - var rights = 0; - for (var i in user.links) { if (i == node.meshid) { rights = user.links[i].rights; } } - if (rights == 0) { res.sendStatus(401); return; } + if (obj.GetMeshRights(user, node.meshid) == 0) { res.sendStatus(401); return; } // Get the list of power events and send them res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' }); @@ -3772,8 +3763,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (agent == null) return; // Check we have agent rights - var rights = user.links[agent.dbMeshKey].rights; - if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); } + if (((obj.GetMeshRights(user, agent.dbMeshKey) & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); } }; // Send the core module to the mesh agent @@ -3787,8 +3777,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (agent == null) return; // Check we have agent rights - var rights = user.links[agent.dbMeshKey].rights; - if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { + if (((obj.GetMeshRights(user, agent.dbMeshKey) & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { if (coretype == 'clear') { // Clear the mesh agent core agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom core. @@ -3907,6 +3896,32 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } }; + // + // Access Control Functions + // + + // Return the node and rights for a given nodeid + obj.GetNodeWithRights = function (domain, user, nodeid, func) { + // Perform user pre-validation + if ((user == null) || (nodeid == null)) { func(null, 0, false); return; } // Invalid user + if (typeof user == 'string') { user = obj.users[user]; } + if ((user == null) || (user.links == null)) { func(null, 0, false); return; } // No rights + + // Perform node pre-validation + if (obj.common.validateString(nodeid, 0, 128) == false) { func(null, 0, false); return; } // Invalid nodeid + const snode = nodeid.split('/'); + if ((snode.length != 3) || (snode[0] != 'node')) { func(null, 0, false); return; } // Invalid nodeid + if ((domain != null) && (snode[1] != domain.id)) { func(null, 0, false); return; } // Invalid domain + + // Check that we have permissions for this node. + db.Get(nodeid, function (err, nodes) { + if ((nodes == null) || (nodes.length != 1)) { func(null, 0, false); return; } // No such nodeid + var rights = user.links[nodes[0].meshid]; + if (rights == null) { func(null, 0, false); return; } // No rights to this mesh + func(nodes[0], rights.rights, true); + }); + } + // Returns a list of all meshes that this user has some rights too obj.GetAllMeshWithRights = function (user, rights) { if (typeof user == 'string') { user = obj.users[user]; } @@ -4076,9 +4091,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (typeof command.sessionid != 'string') return; var splitsessionid = command.sessionid.split('/'); // Check that we are in the same domain and the user has rights over this node. - if ((splitsessionid[0] == 'user') && (splitsessionid[1] == domainid)) { + if ((splitsessionid.length == 4) && (splitsessionid[0] == 'user') && (splitsessionid[1] == domainid)) { // Check if this user has rights to get this message - //if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 16) == 0)) return; // TODO!!!!!!!!!!!!!!!!!!!!! + if (obj.GetMeshRights(splitsessionid[0] + '/' + splitsessionid[1] + '/' + splitsessionid[2], meshid) == 0) return; // TODO: Check if this is ok // See if the session is connected. If so, go ahead and send this message to the target node var ws = obj.wssessions2[command.sessionid]; @@ -4101,7 +4116,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check that we are in the same domain and the user has rights over this node. if ((splituserid[0] == 'user') && (splituserid[1] == domainid)) { // Check if this user has rights to get this message - //if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 16) == 0)) return; // TODO!!!!!!!!!!!!!!!!!!!!! + if (obj.GetMeshRights(command.userid, meshid) == 0) return; // TODO: Check if this is ok // See if the session is connected var sessions = obj.wssessions[command.userid]; @@ -4120,16 +4135,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } else { // Route this command to the mesh command.nodeid = nodeid; var cmdstr = JSON.stringify(command); - for (var userid in obj.wssessions) { // Find all connected users for this mesh and send the message - var user = obj.users[userid]; - if ((user != null) && (user.links != null)) { - var rights = user.links[meshid]; - if (rights != null) { // TODO: Look at what rights are needed for message routing - var xsessions = obj.wssessions[userid]; - // Send the message to all users on this server - for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } } - } - } + if (obj.GetMeshRights(userid, meshid) == 0) return; // TODO: Check if this is ok + + // Find all connected users for this mesh and send the message + for (var userid in obj.wssessions) { + var xsessions = obj.wssessions[userid]; + // Send the message to all users on this server + for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } } } // Send the message to all users of other servers
'; - // Collapsing header & start collapsing area - deviceHeaderId2++; - var collapsed = CollapsedGroups[mesh._id]; - r += ''; // Collapse action + // Collapsing header & start collapsing area + deviceHeaderId2++; + var collapsed = CollapsedGroups[mesh._id]; + r += ''; // Collapse action - r += '' + EscapeHtml(mesh.name) + ''; - r += getMeshActions(mesh, meshrights); - r += '
' + "No Intel® AMT devices in this mesh"; - if ((meshrights & 4) != 0) { r += ', ' + "add one" + ''; } - } - if (mesh.mtype == 2) { - r += '
'; - r += '
'; // Open collapse div - r += '
' + "No devices in this group"; - if ((meshrights & 4) != 0) { r += ', ' + "add one" + ''; } - } - r += '.
' + "No Intel® AMT devices in this mesh"; + if ((meshrights & 4) != 0) { r += ', ' + "add one" + ''; } } + if (mesh.mtype == 2) { + r += '
'; + r += '
'; // Open collapse div + r += '
' + "No devices in this group"; + if ((meshrights & 4) != 0) { r += ', ' + "add one" + ''; } + } + r += '.