diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 5ce6fc57..eca883d4 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index bd6cbbc1..95208c85 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index 8a4919d4..539ede0a 100644 Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ diff --git a/agents/MeshService.exe b/agents/MeshService.exe index 4a2d671a..6f5dd244 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index 77e190cc..eb0b6136 100644 Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index 6c00e6a6..6f1acb8a 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshagent_arm b/agents/meshagent_arm index d2886c33..520f5dcb 100644 Binary files a/agents/meshagent_arm and b/agents/meshagent_arm differ diff --git a/agents/meshagent_pi b/agents/meshagent_pi index ec7f85fb..62f1c83a 100644 Binary files a/agents/meshagent_pi and b/agents/meshagent_pi differ diff --git a/agents/meshagent_pogo b/agents/meshagent_pogo index 7194d555..a81add1b 100644 Binary files a/agents/meshagent_pogo and b/agents/meshagent_pogo differ diff --git a/agents/meshagent_poky b/agents/meshagent_poky index 5787e547..ab4bbf60 100644 Binary files a/agents/meshagent_poky and b/agents/meshagent_poky differ diff --git a/agents/meshagent_poky64 b/agents/meshagent_poky64 index 338ac10a..e722306c 100644 Binary files a/agents/meshagent_poky64 and b/agents/meshagent_poky64 differ diff --git a/agents/meshagent_x86 b/agents/meshagent_x86 index 5c124301..2baa1a60 100644 Binary files a/agents/meshagent_x86 and b/agents/meshagent_x86 differ diff --git a/agents/meshagent_x86-64 b/agents/meshagent_x86-64 index 216f9dd3..526cf0cb 100644 Binary files a/agents/meshagent_x86-64 and b/agents/meshagent_x86-64 differ diff --git a/agents/meshagent_x86-64_nokvm b/agents/meshagent_x86-64_nokvm index ce44d1c8..694774d1 100644 Binary files a/agents/meshagent_x86-64_nokvm and b/agents/meshagent_x86-64_nokvm differ diff --git a/agents/meshagent_x86_nokvm b/agents/meshagent_x86_nokvm index c2223db9..a08ed3c8 100644 Binary files a/agents/meshagent_x86_nokvm and b/agents/meshagent_x86_nokvm differ diff --git a/agents/meshcmd.js b/agents/meshcmd.js index 60b870cf..6775140b 100644 --- a/agents/meshcmd.js +++ b/agents/meshcmd.js @@ -332,6 +332,7 @@ function run(argv) { amtMei.getMACAddresses(function (result) { mestate.mac = result; }); amtMei.getLanInterfaceSettings(0, function (result) { mestate.net0 = result; }); amtMei.getLanInterfaceSettings(1, function (result) { mestate.net1 = result; }); + amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } }); amtMei.getDnsSuffix(function (result) { mestate.dns = result; var str = 'Intel AMT v' + mestate.ver; @@ -341,7 +342,7 @@ function run(argv) { if (mestate.ehbc.EHBC == true) { str += ', EHBC enabled'; } str += '.'; if (mestate.net0 != null) { str += '\r\nWired ' + ((mestate.net0.enabled == 1) ? 'Enabled' : 'Disabled') + ((mestate.net0.dhcpEnabled == 1) ? ', DHCP' : ', Static') + ', ' + mestate.net0.mac + (mestate.net0.address == '0.0.0.0'?'':(', ' + mestate.net0.address)); } - if (mestate.net1 != null) { str += '\r\nWireless ' + ((mestate.net0.enabled == 1) ? 'Enabled' : 'Disabled') + ((mestate.net0.dhcpEnabled == 1) ? ', DHCP' : ', Static') + ', ' + mestate.net0.mac + (mestate.net0.address == '0.0.0.0' ? '' : (', ' + mestate.net0.address)); } + if (mestate.net1 != null) { str += '\r\nWireless ' + ((mestate.net1.enabled == 1) ? 'Enabled' : 'Disabled') + ((mestate.net1.dhcpEnabled == 1) ? ', DHCP' : ', Static') + ', ' + mestate.net1.mac + (mestate.net1.address == '0.0.0.0' ? '' : (', ' + mestate.net1.address)); } console.log(str + '.'); exit(1); }); @@ -369,9 +370,10 @@ function run(argv) { startMeScript(); } else if (settings.action == 'amtuuid') { // Start running - if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } - if ((settings.hostname == null) || (typeof settings.hostname != 'string') || (settings.hostname == '')) { settings.hostname = '127.0.0.1'; } - if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } + if (settings.hostname != null) { + if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } + if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } + } settings.protocol = 'http:'; settings.localport = 16992; debug(1, "Settings: " + JSON.stringify(settings)); @@ -573,8 +575,14 @@ function activeToCCMEx3(stack, name, responses, status) { // Called to get the UUID of Intel AMT, start by setting up MicroLMS if we are doing the operation on the local computer function getAmtUuid() { - // See if MicroLMS needs to be started - if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) { settings.noconsole = true; startLms(getAmtUuidEx); } else { getAmtUuidEx() }; + if (settings.hostname == null) { + var amtMeiModule = require('amt-mei'); + var amtMei = new amtMeiModule(); + amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); + amtMei.getUuid(function (result) { if ((result == null) || (result.uuid == null)) { console.log('Failed.'); } else { console.log(result.uuid); } exit(1); }); + } else { + if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) { settings.noconsole = true; startLms(getAmtUuidEx); return; } else { getAmtUuidEx(); } + } } // Fetch the computer's UUID by fetching the CIM_ComputerSystemPackage WSMAN object. @@ -677,10 +685,22 @@ function saveEntireAmtStateDone() { // Get Intel AMT information using MEI // TODO: If this call is called many time at once, it's going to cause issues. +var getAmtInfoFetching = null; +var getAmtInfoFetchingTimer = null; function getAmtInfo(func, tag) { - //console.log('getAmtInfo1'); if (amtMei == null) { if (func != null) { func(null, tag); } return; } + if (getAmtInfoFetching != null) { getAmtInfoFetching.push({ f: func, t: tag }); return; } + getAmtInfoFetching = [{ f: func, t: tag }]; amtMeiTmpState = { Flags: 0, TrustedHashes: [] }; // Flags: 1=EHBC, 2=CCM, 4=ACM + getAmtInfoFetchingTimer = setTimeout(function () { + // MEI failed to respond, break out and reset everthing. + for (var i in getAmtInfoFetching) { if (getAmtInfoFetching[i].f != null) { getAmtInfoFetching[i].f(amtMeiTmpState, getAmtInfoFetching[i].t); } } + getAmtInfoFetching = null; + getAmtInfoFetchingTimer = null; + var amtMeiModule = require('amt-mei'); + amtMei = new amtMeiModule(); + amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); + }, 3000); amtMei.getProtocolVersion(function (result) { if (result != null) { amtMeiTmpState.MeiVersion = result; } }); amtMei.getVersion(function (val) { amtMeiTmpState.Versions = {}; @@ -699,9 +719,10 @@ function getAmtInfo(func, tag) { amtMeiTmpState.TrustedHashes.push({ Active: result.isActive, Default: result.isDefault, HashAlgorithm: result.hashAlgorithm, Name: result.name, Hash: result.certificateHash }); if (--exitOnCount == 0) { amtMeiTmpState.Notifications = lmsNotifications; amtMeiState = amtMeiTmpState; - //console.log('getAmtInfo2', JSON.stringify(amtMeiState)); - if (func != null) { func(amtMeiTmpState, tag); } - amtMeiTmpState = null; + for (var i in getAmtInfoFetching) { if (getAmtInfoFetching[i].f != null) { getAmtInfoFetching[i].f(amtMeiTmpState, getAmtInfoFetching[i].t); } } + getAmtInfoFetching = null; + clearTimeout(getAmtInfoFetchingTimer); + getAmtInfoFetchingTimer = null; } }); } diff --git a/agents/meshcore.js b/agents/meshcore.js index 6626932d..9eae6e2a 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1178,6 +1178,7 @@ function createMeshCore(agent) { if (meinfo.ProvisioningState) { intelamt.state = meinfo.ProvisioningState; p = true; } if (meinfo.flags) { intelamt.flags = meinfo.Flags; p = true; } if (meinfo.OsHostname) { intelamt.host = meinfo.OsHostname; p = true; } + if (meinfo.UUID) { intelamt.uuid = meinfo.UUID; p = true; } if (p == true) { r.intelamt = intelamt } } func(r); @@ -1221,6 +1222,7 @@ function createMeshCore(agent) { amtMei.getProvisioningState(function (result) { amtMeiTmpState.ProvisioningState = result.state; }); amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } }); amtMei.getControlMode(function (result) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } }); + amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { amtMeiTmpState.UUID = result.uuid; } }); //amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; }); amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } if (func != null) { func(amtMeiTmpState); } }); } diff --git a/agents/modules_meshcmd/amt-mei.js b/agents/modules_meshcmd/amt-mei.js index 16de7862..479025f8 100644 --- a/agents/modules_meshcmd/amt-mei.js +++ b/agents/modules_meshcmd/amt-mei.js @@ -105,6 +105,34 @@ function amt_heci() { }, callback, optional); }; + // Fill the left with zeros until the string is of a given length + function zeroLeftPad(str, len) { + if ((len == null) && (typeof (len) != 'number')) { return null; } + if (str == null) str = ''; // If null, this is to generate zero leftpad string + var zlp = ''; + for (var i = 0; i < len - str.length; i++) { zlp += '0'; } + return zlp + str; + } + + this.getUuid = function getUuid(callback) { + var optional = []; + for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); } + this.sendCommand(0x5c, null, function (header, fn, opt) { + if (header.Status == 0) { + var result = {}; + result.uuid = [zeroLeftPad(header.Data.readUInt32LE(0).toString(16), 8), + zeroLeftPad(header.Data.readUInt16LE(4).toString(16), 4), + zeroLeftPad(header.Data.readUInt16LE(6).toString(16), 4), + zeroLeftPad(header.Data.readUInt16BE(8).toString(16), 4), + zeroLeftPad(header.Data.slice(10).toString('hex').toLowerCase(), 12)].join('-'); + opt.unshift(result); + } else { + opt.unshift(null); + } + fn.apply(this, opt); + }, callback, optional); + }; + this.getProvisioningState = function getProvisioningState(callback) { var optional = []; for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); } diff --git a/agents/modules_meshcore/amt-mei.js b/agents/modules_meshcore/amt-mei.js index ffe504c5..479025f8 100644 --- a/agents/modules_meshcore/amt-mei.js +++ b/agents/modules_meshcore/amt-mei.js @@ -23,15 +23,18 @@ function amt_heci() { this._ObjectID = "pthi"; this._rq = new Q(); - this._setupPTHI = function _setupPTHI() { + this._setupPTHI = function _setupPTHI() + { this._amt = heci.create(); this._amt.BiosVersionLen = 65; this._amt.UnicodeStringLen = 20; this._amt.Parent = this; this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); }); - this._amt.on('connect', function _amtOnConnect() { - this.on('data', function _amtOnData(chunk) { + this._amt.on('connect', function _amtOnConnect() + { + this.on('data', function _amtOnData(chunk) + { //console.log("Received: " + chunk.length + " bytes"); var header = this.Parent.getCommand(chunk); //console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse); @@ -43,12 +46,14 @@ function amt_heci() { params.unshift(header); callback.apply(this.Parent, params); - if (this.Parent._rq.isEmpty()) { + if(this.Parent._rq.isEmpty()) + { // No More Requests, we can close PTHI this.Parent._amt.disconnect(); this.Parent._amt = null; } - else { + else + { // Send the next request this.write(this.Parent._rq.peekQueue().send); } @@ -73,9 +78,10 @@ function amt_heci() { var header = Buffer.from('010100000000000000000000', 'hex'); header.writeUInt32LE(arguments[0] | 0x04000000, 4); header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8); - this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args, send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]])) }); + this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args , send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]]))}); - if (!this._amt) { + if(!this._amt) + { this._setupPTHI(); this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 }); } @@ -87,7 +93,7 @@ function amt_heci() { this.sendCommand(26, null, function (header, fn, opt) { if (header.Status == 0) { var i, CodeVersion = header.Data, val = { BiosVersion: CodeVersion.slice(0, this._amt.BiosVersionLen), Versions: [] }, v = CodeVersion.slice(this._amt.BiosVersionLen + 4); - for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen); ++i) { + for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen) ; ++i) { val.Versions[i] = { Description: v.slice(2, v.readUInt16LE(0) + 2).toString(), Version: v.slice(4 + this._amt.UnicodeStringLen, 4 + this._amt.UnicodeStringLen + v.readUInt16LE(2 + this._amt.UnicodeStringLen)).toString() }; v = v.slice(4 + (2 * this._amt.UnicodeStringLen)); } @@ -99,6 +105,34 @@ function amt_heci() { }, callback, optional); }; + // Fill the left with zeros until the string is of a given length + function zeroLeftPad(str, len) { + if ((len == null) && (typeof (len) != 'number')) { return null; } + if (str == null) str = ''; // If null, this is to generate zero leftpad string + var zlp = ''; + for (var i = 0; i < len - str.length; i++) { zlp += '0'; } + return zlp + str; + } + + this.getUuid = function getUuid(callback) { + var optional = []; + for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); } + this.sendCommand(0x5c, null, function (header, fn, opt) { + if (header.Status == 0) { + var result = {}; + result.uuid = [zeroLeftPad(header.Data.readUInt32LE(0).toString(16), 8), + zeroLeftPad(header.Data.readUInt16LE(4).toString(16), 4), + zeroLeftPad(header.Data.readUInt16LE(6).toString(16), 4), + zeroLeftPad(header.Data.readUInt16BE(8).toString(16), 4), + zeroLeftPad(header.Data.slice(10).toString('hex').toLowerCase(), 12)].join('-'); + opt.unshift(result); + } else { + opt.unshift(null); + } + fn.apply(this, opt); + }, callback, optional); + }; + this.getProvisioningState = function getProvisioningState(callback) { var optional = []; for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); } @@ -248,6 +282,46 @@ function amt_heci() { fn.apply(this, opt); }, callback, optional); } + this.getLanInterfaceSettings = function getLanInterfaceSettings(index, callback) + { + var optional = []; + for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); } + var ifx = Buffer.alloc(4); + ifx.writeUInt32LE(index); + this.sendCommand(0x48, ifx, function onGetLanInterfaceSettings(header, fn, opt) + { + if(header.Status == 0) + { + var info = {}; + info.enabled = header.Data.readUInt32LE(0); + info.dhcpEnabled = header.Data.readUInt32LE(8); + switch(header.Data[12]) + { + case 1: + info.dhcpMode = 'ACTIVE' + break; + case 2: + info.dhcpMode = 'PASSIVE' + break; + default: + info.dhcpMode = 'UNKNOWN'; + break; + } + info.mac = header.Data.slice(14).toString('hex:'); + + var addr = header.Data.readUInt32LE(4); + info.address = ((addr >> 24) & 255) + '.' + ((addr >> 16) & 255) + '.' + ((addr >> 8) & 255) + '.' + (addr & 255); + opt.unshift(info); + fn.apply(this, opt); + } + else + { + opt.unshift(null); + fn.apply(this, opt); + } + }, callback, optional); + + }; this.unprovision = function unprovision(mode, callback) { var optional = []; for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); } diff --git a/db.js b/db.js index a89aa884..d5bba0fe 100644 --- a/db.js +++ b/db.js @@ -107,6 +107,7 @@ module.exports.CreateDB = function (args, datapath) { obj.clearOldEntries = function (type, days, domain) { var cutoff = Date.now() - (1000 * 60 * 60 * 24 * days); obj.file.remove({ type: type, time: { $lt: cutoff } }, { multi: true }); } obj.getPowerTimeline = function (nodeid, func) { if (obj.databaseType == 1) { obj.file.find({ type: 'power', node: { $in: ['*', nodeid] } }).sort({ time: 1 }).exec(func); } else { obj.file.find({ type: 'power', node: { $in: ['*', nodeid] } }).sort({ time: 1 }, func); } } obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); } + obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); } // This is used to rate limit a number of operation per day. Returns a startValue each new days, but you can substract it and save the value in the db. obj.getValueOfTheDay = function (id, startValue, func) { obj.Get(id, function (err, docs) { var date = new Date(), t = date.toLocaleDateString(); if (docs.length == 1) { var r = docs[0]; if (r.day == t) { func({ _id: id, value: r.value, day: t }); return; } } func({ _id: id, value: startValue, day: t }); }); } diff --git a/meshagent.js b/meshagent.js index 3b41a3fe..9a3b510e 100644 --- a/meshagent.js +++ b/meshagent.js @@ -549,6 +549,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (device.intelamt.state != command.intelamt.state) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); } if (device.intelamt.flags != command.intelamt.flags) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); } if (device.intelamt.host != command.intelamt.host) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); } + if (device.intelamt.uuid != command.intelamt.uuid) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); } } if (mesh.mtype == 2) { if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); } diff --git a/meshcentral.js b/meshcentral.js index 12292997..291fec2a 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -227,6 +227,7 @@ function CreateMeshCentralServer(config, args) { //if (obj.servicelog != null) { var s = ''; for (var i in obj.args) { if (i != '_') { if (s.length > 0) { s += ', '; } s += i + "=" + obj.args[i]; } } logInfoEvent('MeshServer started with arguments: ' + s); } // Look at passed in arguments + if ((obj.args.user != null) && (typeof obj.args.user != 'string')) { delete obj.args.user; } if ((obj.args.ciralocalfqdn != null) && ((obj.args.lanonly == true) || (obj.args.wanonly == true))) { console.log("WARNING: CIRA local FQDN's ignored when server in LAN-only or WAN-only mode."); } if ((obj.args.ciralocalfqdn != null) && (obj.args.ciralocalfqdn.split(',').length > 4)) { console.log("WARNING: Can't have more than 4 CIRA local FQDN's. Ignoring value."); obj.args.ciralocalfqdn = null; } if (obj.args.port == null || typeof obj.args.port != 'number') { if (obj.args.notls == null) { obj.args.port = 443; } else { obj.args.port = 80; } } diff --git a/meshrelay.js b/meshrelay.js index 7e78945f..4550faeb 100644 --- a/meshrelay.js +++ b/meshrelay.js @@ -69,7 +69,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) { obj.parent.authenticate(req.query.user, req.query.pass, obj.domain, function (err, userid, passhint) { if (userid != null) { obj.authenticated = true; - // Check is we have agent routing instructions, process this here. + // Check if we have agent routing instructions, process this here. if ((req.query.nodeid != null) && (req.query.tcpport != null)) { if (obj.id == undefined) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one. var command = { nodeid: req.query.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id, tcpport: req.query.tcpport, tcpaddr: ((req.query.tcpaddr == null) ? '127.0.0.1' : req.query.tcpaddr) }; diff --git a/meshuser.js b/meshuser.js index 9b50934a..9b52c8e0 100644 --- a/meshuser.js +++ b/meshuser.js @@ -167,7 +167,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { case 'files': { // Send the full list of server files to the browser app - if ((user.siteadmin & 8) != 0) { updateUserFiles(user, ws, domain); } + if ((user != null) && (user.siteadmin != null) && (user.siteadmin & 8) != 0) { updateUserFiles(user, ws, domain); } break; } case 'fileoperation': @@ -205,7 +205,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { if (agent != null) { // Check if we have permission to send a message to that node var rights = user.links[agent.dbMeshKey]; - if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking + if ((rights != null) && ((rights.rights & 8) != 0)) { // 8 is remote control permission command.sessionid = ws.sessionId; // Set the session id, required for responses. command.rights = rights.rights; // Add user rights flags to the message delete command.nodeid; // Remove the nodeid since it's implyed. @@ -217,7 +217,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { if (routing != null) { // Check if we have permission to send a message to that node var rights = user.links[routing.meshid]; - if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking + if ((rights != null) && ((rights.rights & 8) != 0)) { // 8 is remote control permission command.fromSessionid = ws.sessionId; // Set the session id, required for responses. command.rights = rights.rights; // Add user rights flags to the message obj.parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid); diff --git a/mpsserver.js b/mpsserver.js index 414e9356..0e00588c 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -227,44 +227,75 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { obj.db.GetAllType('mesh', function (err, docs) { var mesh = null; for (var i in docs) { if (docs[i]._id.indexOf(meshIdStart) > 0) { mesh = docs[i]; break; } } - if (mesh == null) { Debug(1, 'MPS:Mesh not found', username, password);SendUserAuthFail(socket); return -1; } + if (mesh == null) { Debug(1, 'MPS:Mesh not found', username, password); SendUserAuthFail(socket); return -1; } - // Intel AMT GUID (socket.tag.SystemId) will be used at NodeID - var systemid = socket.tag.SystemId.split('-').join(''); - var nodeid = new Buffer(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); - socket.tag.name = ''; - socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded - socket.tag.meshid = mesh._id; + // If this is a agent-less mesh, use the device guid 3 times as ID. + if (mesh.mtype == 1) { + // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID + var systemid = socket.tag.SystemId.split('-').join(''); + var nodeid = new Buffer(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); + socket.tag.name = ''; + socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded + socket.tag.meshid = mesh._id; + socket.tag.connectTime = Date.now(); - obj.db.Get(socket.tag.nodeid, function (err, nodes) { - if (nodes.length == 0) { - if (mesh.mtype == 1) { - // Node is not in the database, add it. Credentials will be empty until added by the user. - var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0 } }; - obj.db.Set(device); + obj.db.Get(socket.tag.nodeid, function (err, nodes) { + if (nodes.length == 0) { + if (mesh.mtype == 1) { + // Node is not in the database, add it. Credentials will be empty until added by the user. + var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0 } }; + obj.db.Set(device); - // Event the new node - var device2 = common.Clone(device); - if (device2.intelamt.pass != undefined) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }) + // Event the new node + var device2 = common.Clone(device); + if (device2.intelamt.pass != undefined) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }) + } else { + // New CIRA connection for unknown node, disconnect. + console.log('CIRA connection for unknown node with incorrect mesh type. meshid: ' + socket.tag.meshid); + socket.end(); + return; + } } else { + // Node is already present + var node = nodes[0]; + if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; } + } + + // Add the connection to the MPS connection list + obj.ciraConnections[socket.tag.nodeid] = socket; + obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. + SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection + }); + } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID + // Intel AMT GUID (socket.tag.SystemId) will be used to search the node + obj.db.getAmtUuidNode(mesh._id, socket.tag.SystemId, function (err, nodes) { + if (nodes.length == 0) { // New CIRA connection for unknown node, disconnect. - console.log('CIRA connection for unknown node with incorrect mesh type. meshid: ' + socket.tag.meshid); + console.log('CIRA connection for unknown node. meshid: ' + mesh._id + ', uuid: ' + systemid); socket.end(); return; } - } else { - // Node is already present + + // Node is present var node = nodes[0]; if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; } - } + socket.tag.nodeid = node._id; + socket.tag.meshid = mesh._id; + socket.tag.connectTime = Date.now(); - // Add the connection to the MPS connection list - obj.ciraConnections[socket.tag.nodeid] = socket; - obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. - SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection - }); + // Add the connection to the MPS connection list + obj.ciraConnections[socket.tag.nodeid] = socket; + obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. + SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection + }); + } else { // Unknown mesh type + // New CIRA connection for unknown node, disconnect. + console.log('CIRA connection to a unknown mesh type. meshid: ' + socket.tag.meshid); + socket.end(); + return; + } }); return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen; } diff --git a/package.json b/package.json index af199d70..c0195ca6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.1.5-e", + "version": "0.1.5-k", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/scripts/agent-desktop-0.0.2.js b/public/scripts/agent-desktop-0.0.2.js index fba6996b..e502c598 100644 --- a/public/scripts/agent-desktop-0.0.2.js +++ b/public/scripts/agent-desktop-0.0.2.js @@ -159,7 +159,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) { } obj.ProcessScreenMsg = function (width, height) { - //obj.Debug("ProcessScreenMsg: " + width + " x " + height); + obj.Debug("ScreenSize: " + width + " x " + height); obj.Canvas.setTransform(1, 0, 0, 1, 0, 0); obj.rotation = 0; obj.FirstDraw = true; diff --git a/views/default.handlebars b/views/default.handlebars index d750cda0..3648bfab 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1468,10 +1468,10 @@ function getMeshActions(mesh, meshrights) { if ((meshrights & 4) == 0) return ''; var r = ''; + if ((features & 2) == 0) { // If not LAN-Only + r += ' Add CIRA'; + } if (mesh.mtype == 1) { - if ((features & 2) == 0) { // If not LAN-Only - r += ' Add CIRA'; - } if ((features & 1) == 0) { // If not WAN-Only r += ' Add Local'; r += ' Scan Network'; @@ -2580,7 +2580,7 @@ if (mesh.mtype == 2) x += 'Interfaces '; if (xxmap != null) x += 'Location '; - if (mesh.mtype == 2) x += 'Router '; + if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += 'Router '; // RDP link, show this link only of the remote machine is Windows. if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) { @@ -2616,11 +2616,11 @@ // Show or hide the tabs // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent // node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console - QV('MainDevDesktop', (mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0)); - QV('MainDevTerminal', (mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0)); - QV('MainDevFiles', (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))); - QV('MainDevAmt', node.intelamt != null); - QV('MainDevConsole', consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))); + QV('MainDevDesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0)) && (meshrights & 8)); + QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0)) && (meshrights & 8)); + QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8)); + QV('MainDevAmt', (node.intelamt != null) && (meshrights & 8)); + QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8)); QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0) && (userinfo.siteadmin == 0xFFFFFFFF)); QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:''); @@ -4041,8 +4041,12 @@ c++; count++; - // Mesh - var rights = 'Administrator'; // TODO + // Mesh rights + var meshrights = meshes[i].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights; + var rights = 'Partial Rights'; + if (meshrights == 0xFFFFFFFF) rights = 'Full Administrator'; else if (meshrights == 0) rights = 'No Rights'; + + // Print the mesh information r += '