More access control improvements, RPi icon.
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
930
meshuser.js
58
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\n<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>MeshCentral2 MPS server.<br />Intel® AMT computers should connect here.</body></html>"); 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\n<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>MeshCentral2 MPS server.<br />Intel® AMT computers should connect here.</body></html>"); 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'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.4.6-p",
|
||||
"version": "0.4.6-q",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 4.0 KiB |
BIN
public/images/icons256-7-1.png
Normal file
After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 46 KiB |
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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 = '<span style=color:lightgray>' + ", Intel® AMT only" + '</span>'; }
|
||||
if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||||
r += '<div class=DevSt style=padding-top:4px><span style=float:right>';
|
||||
//r += getMeshActions(mesh2, meshrights);
|
||||
//r += getMeshActions(meshes[nodes[i].meshid], meshrights);
|
||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
|
||||
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 += '</tr></table>'; }
|
||||
r += '<div><div colspan=3 class=DevSt><span style=float:right>';
|
||||
//r += getMeshActions(mesh, meshrights);
|
||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
|
||||
if (mesh.mtype == 1) { r += '<div style=padding:10px><i>' + "No Intel® AMT devices in this group"; }
|
||||
if (mesh.mtype == 2) { r += '<div style=padding:10px><i>' + "No devices in this group"; }
|
||||
r += '.</i></div></div>';
|
||||
current = mesh._id;
|
||||
count++;
|
||||
}
|
||||
var mesh = meshes[i];
|
||||
if (IsMeshViewable(mesh)) {
|
||||
if ((current != '') && (r != '')) { r += '</tr></table>'; }
|
||||
r += '<div><div colspan=3 class=DevSt><span style=float:right>';
|
||||
//r += getMeshActions(mesh, meshrights);
|
||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
|
||||
if (mesh.mtype == 1) { r += '<div style=padding:10px><i>' + "No Intel® AMT devices in this group"; }
|
||||
if (mesh.mtype == 2) { r += '<div style=padding:10px><i>' + "No devices in this group"; }
|
||||
r += '.</i></div></div>';
|
||||
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." + '<br /><br />';
|
||||
var y = '<select id=d2deviceop style=float:right;width:170px>';
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
@ -2117,7 +2103,7 @@
|
||||
|
||||
function editDeviceAmtSettings(nodeid, func) {
|
||||
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", '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
x += addHtmlValue("Password", '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
@ -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 = '<table align=center><td>';
|
||||
x += '<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>';
|
||||
@ -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();*/ }
|
||||
|
@ -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 += '</tr></table>'; }
|
||||
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt>';
|
||||
var mesh = meshes[i], meshrights = GetMeshRights(mesh);
|
||||
if (displayedMeshes[mesh._id] == null) {
|
||||
if ((current != '') && (r != '')) { r += '</tr></table>'; }
|
||||
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt>';
|
||||
|
||||
// Collapsing header & start collapsing area
|
||||
deviceHeaderId2++;
|
||||
var collapsed = CollapsedGroups[mesh._id];
|
||||
r += '<img class=collapseImage id=\"DevxColImg' + deviceHeaderId2 + '\" src=images/c' + ((collapsed === true)?'1':'2') + '.png height=8 width=8 style=margin-left:2px;margin-right:2px;cursor:pointer onclick=toggleCollapseGroup(\"' + deviceHeaderId2 + '\",\"' + mesh._id + '\")></img>'; // Collapse action
|
||||
// Collapsing header & start collapsing area
|
||||
deviceHeaderId2++;
|
||||
var collapsed = CollapsedGroups[mesh._id];
|
||||
r += '<img class=collapseImage id=\"DevxColImg' + deviceHeaderId2 + '\" src=images/c' + ((collapsed === true)?'1':'2') + '.png height=8 width=8 style=margin-left:2px;margin-right:2px;cursor:pointer onclick=toggleCollapseGroup(\"' + deviceHeaderId2 + '\",\"' + mesh._id + '\")></img>'; // Collapse action
|
||||
|
||||
r += '<span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span><span>';
|
||||
r += getMeshActions(mesh, meshrights);
|
||||
r += '</span></td></tr><tr>';
|
||||
if (mesh.mtype == 1) {
|
||||
r += '<td><div style=padding:10px><i>' + "No Intel® AMT devices in this mesh";
|
||||
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
|
||||
}
|
||||
if (mesh.mtype == 2) {
|
||||
r += '<td>';
|
||||
r += '<div id=DevxCol' + deviceHeaderId2 + ((collapsed === true)?' style=display:none':'') + '>'; // Open collapse div
|
||||
r += '<div style=padding:10px><i>' + "No devices in this group";
|
||||
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
|
||||
}
|
||||
r += '.</i></div></td>';
|
||||
r += '</div>'; // End collapsing area
|
||||
|
||||
current = mesh._id;
|
||||
count++;
|
||||
r += '<span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span><span>';
|
||||
r += getMeshActions(mesh, meshrights);
|
||||
r += '</span></td></tr><tr>';
|
||||
if (mesh.mtype == 1) {
|
||||
r += '<td><div style=padding:10px><i>' + "No Intel® AMT devices in this mesh";
|
||||
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
|
||||
}
|
||||
if (mesh.mtype == 2) {
|
||||
r += '<td>';
|
||||
r += '<div id=DevxCol' + deviceHeaderId2 + ((collapsed === true)?' style=display:none':'') + '>'; // Open collapse div
|
||||
r += '<div style=padding:10px><i>' + "No devices in this group";
|
||||
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
|
||||
}
|
||||
r += '.</i></div></td>';
|
||||
r += '</div>'; // 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 += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
|
||||
var rights = GetNodeRights(node);
|
||||
if (((node.conn & 1) != 0) && ((rights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
|
||||
}
|
||||
|
||||
var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '<br /><br />';
|
||||
@ -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." + '<br /><br />';
|
||||
var y = '<select id=d2deviceop style=float:right;width:250px>';
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((meshrights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((rights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((rights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((rights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
y += '</select>';
|
||||
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", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
x += addHtmlValue("Password", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
@ -5049,7 +5035,7 @@
|
||||
// List all available alternative groups
|
||||
var y = '<select id=p10newGroup style=width:236px>', count = 0;
|
||||
for (var i in meshes) {
|
||||
var meshrights = meshes[i].links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(i);
|
||||
if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
|
||||
}
|
||||
y += '</select>';
|
||||
@ -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 = '<br><div style=display:inline-block;width:40px></div>';
|
||||
var x = '<br><div style=display:inline-block;width:16px></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i1 onclick=p10setIcon(1) onkeypress="if (event.key==\'Enter\') p10setIcon(1)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i2 onclick=p10setIcon(2) onkeypress="if (event.key==\'Enter\') p10setIcon(2)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i3 onclick=p10setIcon(3) onkeypress="if (event.key==\'Enter\') p10setIcon(3)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i4 onclick=p10setIcon(4) onkeypress="if (event.key==\'Enter\') p10setIcon(4)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i5 onclick=p10setIcon(5) onkeypress="if (event.key==\'Enter\') p10setIcon(5)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div><br><br>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i7 onclick=p10setIcon(7) onkeypress="if (event.key==\'Enter\') p10setIcon(7)"></div><br><br>';
|
||||
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 += '<br><input type=button value=' + "Notes" + ' title=\"' + "View notes about this device group" + '\" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />'; }
|
||||
|
||||
x += '<br style=clear:both><br>';
|
||||
var currentMeshLinks = currentMesh.links[userinfo._id];
|
||||
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Users" + '</a>'; }
|
||||
if (meshrights & 2) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Users" + '</a>'; }
|
||||
|
||||
if ((meshrights & 4) != 0) {
|
||||
if (meshrights & 4) {
|
||||
if (currentMesh.mtype == 1) {
|
||||
x += '<a href=# onclick=\'return addCiraDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new Intel® AMT computer that is located on the internet." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Install CIRA" + '</a>';
|
||||
x += '<a href=# onclick=\'return addDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new Intel® AMT computer that is located on the local network." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Install local" + '</a>';
|
||||
@ -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 {
|
||||
|
76
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
|
||||
|