Access permission and CIRA improvements.
Ylian Saint-Hilaire committed
Mar 26, 2018 at 17:13 UTC
ca94c192ace74b7d008ed6f6eab449103b7257d0
29 files changed
+245
-65
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService.exe
Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/MeshService64.exe
Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ
agents/meshagent_arm
Binary files a/agents/meshagent_arm and b/agents/meshagent_arm differ
agents/meshagent_pi
Binary files a/agents/meshagent_pi and b/agents/meshagent_pi differ
agents/meshagent_pogo
Binary files a/agents/meshagent_pogo and b/agents/meshagent_pogo differ
agents/meshagent_poky
Binary files a/agents/meshagent_poky and b/agents/meshagent_poky differ
agents/meshagent_poky64
Binary files a/agents/meshagent_poky64 and b/agents/meshagent_poky64 differ
agents/meshagent_x86
Binary files a/agents/meshagent_x86 and b/agents/meshagent_x86 differ
agents/meshagent_x86-64
Binary files a/agents/meshagent_x86-64 and b/agents/meshagent_x86-64 differ
agents/meshagent_x86-64_nokvm
Binary files a/agents/meshagent_x86-64_nokvm and b/agents/meshagent_x86-64_nokvm differ
agents/meshagent_x86_nokvm
Binary files a/agents/meshagent_x86_nokvm and b/agents/meshagent_x86_nokvm differ
agents/meshcmd.js
+31
-10
@@ -332,6 +332,7 @@ function run(argv) {
332
amtMei.getMACAddresses(function (result) { mestate.mac = result; });
333
amtMei.getLanInterfaceSettings(0, function (result) { mestate.net0 = result; });
334
amtMei.getLanInterfaceSettings(1, function (result) { mestate.net1 = result; });
335
+ amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } });
336
amtMei.getDnsSuffix(function (result) {
337
mestate.dns = result;
338
var str = 'Intel AMT v' + mestate.ver;
@@ -341,7 +342,7 @@ function run(argv) {
342
if (mestate.ehbc.EHBC == true) { str += ', EHBC enabled'; }
343
str += '.';
344
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)); }
344
- 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)); }
345
+ 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)); }
346
console.log(str + '.');
347
exit(1);
348
});
@@ -369,9 +370,10 @@ function run(argv) {
370
startMeScript();
371
} else if (settings.action == 'amtuuid') {
372
// Start running
372
- if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
373
- if ((settings.hostname == null) || (typeof settings.hostname != 'string') || (settings.hostname == '')) { settings.hostname = '127.0.0.1'; }
374
- if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
373
+ if (settings.hostname != null) {
374
+ if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
375
+ if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
376
+ }
377
settings.protocol = 'http:';
378
settings.localport = 16992;
379
debug(1, "Settings: " + JSON.stringify(settings));
@@ -573,8 +575,14 @@ function activeToCCMEx3(stack, name, responses, status) {
575
576
// Called to get the UUID of Intel AMT, start by setting up MicroLMS if we are doing the operation on the local computer
577
function getAmtUuid() {
576
- // See if MicroLMS needs to be started
577
- if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) { settings.noconsole = true; startLms(getAmtUuidEx); } else { getAmtUuidEx() };
578
+ if (settings.hostname == null) {
579
+ var amtMeiModule = require('amt-mei');
580
+ var amtMei = new amtMeiModule();
581
+ amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; });
582
+ amtMei.getUuid(function (result) { if ((result == null) || (result.uuid == null)) { console.log('Failed.'); } else { console.log(result.uuid); } exit(1); });
583
+ } else {
584
+ if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) { settings.noconsole = true; startLms(getAmtUuidEx); return; } else { getAmtUuidEx(); }
585
+ }
586
}
587
588
// Fetch the computer's UUID by fetching the CIM_ComputerSystemPackage WSMAN object.
@@ -677,10 +685,22 @@ function saveEntireAmtStateDone() {
685
686
// Get Intel AMT information using MEI
687
// TODO: If this call is called many time at once, it's going to cause issues.
688
+var getAmtInfoFetching = null;
689
+var getAmtInfoFetchingTimer = null;
690
function getAmtInfo(func, tag) {
681
- //console.log('getAmtInfo1');
691
if (amtMei == null) { if (func != null) { func(null, tag); } return; }
692
+ if (getAmtInfoFetching != null) { getAmtInfoFetching.push({ f: func, t: tag }); return; }
693
+ getAmtInfoFetching = [{ f: func, t: tag }];
694
amtMeiTmpState = { Flags: 0, TrustedHashes: [] }; // Flags: 1=EHBC, 2=CCM, 4=ACM
695
+ getAmtInfoFetchingTimer = setTimeout(function () {
696
+ // MEI failed to respond, break out and reset everthing.
697
+ for (var i in getAmtInfoFetching) { if (getAmtInfoFetching[i].f != null) { getAmtInfoFetching[i].f(amtMeiTmpState, getAmtInfoFetching[i].t); } }
698
+ getAmtInfoFetching = null;
699
+ getAmtInfoFetchingTimer = null;
700
+ var amtMeiModule = require('amt-mei');
701
+ amtMei = new amtMeiModule();
702
+ amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; });
703
+ }, 3000);
704
amtMei.getProtocolVersion(function (result) { if (result != null) { amtMeiTmpState.MeiVersion = result; } });
705
amtMei.getVersion(function (val) {
706
amtMeiTmpState.Versions = {};
@@ -699,9 +719,10 @@ function getAmtInfo(func, tag) {
719
amtMeiTmpState.TrustedHashes.push({ Active: result.isActive, Default: result.isDefault, HashAlgorithm: result.hashAlgorithm, Name: result.name, Hash: result.certificateHash });
720
if (--exitOnCount == 0) {
721
amtMeiTmpState.Notifications = lmsNotifications; amtMeiState = amtMeiTmpState;
702
- //console.log('getAmtInfo2', JSON.stringify(amtMeiState));
703
- if (func != null) { func(amtMeiTmpState, tag); }
704
- amtMeiTmpState = null;
722
+ for (var i in getAmtInfoFetching) { if (getAmtInfoFetching[i].f != null) { getAmtInfoFetching[i].f(amtMeiTmpState, getAmtInfoFetching[i].t); } }
723
+ getAmtInfoFetching = null;
724
+ clearTimeout(getAmtInfoFetchingTimer);
725
+ getAmtInfoFetchingTimer = null;
726
}
727
});
728
}
agents/meshcore.js
+2
@@ -1178,6 +1178,7 @@ function createMeshCore(agent) {
1178
if (meinfo.ProvisioningState) { intelamt.state = meinfo.ProvisioningState; p = true; }
1179
if (meinfo.flags) { intelamt.flags = meinfo.Flags; p = true; }
1180
if (meinfo.OsHostname) { intelamt.host = meinfo.OsHostname; p = true; }
1181
+ if (meinfo.UUID) { intelamt.uuid = meinfo.UUID; p = true; }
1182
if (p == true) { r.intelamt = intelamt }
1183
}
1184
func(r);
@@ -1221,6 +1222,7 @@ function createMeshCore(agent) {
1222
amtMei.getProvisioningState(function (result) { amtMeiTmpState.ProvisioningState = result.state; });
1223
amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } });
1224
amtMei.getControlMode(function (result) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } });
1225
+ amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { amtMeiTmpState.UUID = result.uuid; } });
1226
//amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; });
1227
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } if (func != null) { func(amtMeiTmpState); } });
1228
}
agents/modules_meshcmd/amt-mei.js
+28
@@ -105,6 +105,34 @@ function amt_heci() {
105
}, callback, optional);
106
};
107
108
+ // Fill the left with zeros until the string is of a given length
109
+ function zeroLeftPad(str, len) {
110
+ if ((len == null) && (typeof (len) != 'number')) { return null; }
111
+ if (str == null) str = ''; // If null, this is to generate zero leftpad string
112
+ var zlp = '';
113
+ for (var i = 0; i < len - str.length; i++) { zlp += '0'; }
114
+ return zlp + str;
115
+ }
116
+
117
+ this.getUuid = function getUuid(callback) {
118
+ var optional = [];
119
+ for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
120
+ this.sendCommand(0x5c, null, function (header, fn, opt) {
121
+ if (header.Status == 0) {
122
+ var result = {};
123
+ result.uuid = [zeroLeftPad(header.Data.readUInt32LE(0).toString(16), 8),
124
+ zeroLeftPad(header.Data.readUInt16LE(4).toString(16), 4),
125
+ zeroLeftPad(header.Data.readUInt16LE(6).toString(16), 4),
126
+ zeroLeftPad(header.Data.readUInt16BE(8).toString(16), 4),
127
+ zeroLeftPad(header.Data.slice(10).toString('hex').toLowerCase(), 12)].join('-');
128
+ opt.unshift(result);
129
+ } else {
130
+ opt.unshift(null);
131
+ }
132
+ fn.apply(this, opt);
133
+ }, callback, optional);
134
+ };
135
+
136
this.getProvisioningState = function getProvisioningState(callback) {
137
var optional = [];
138
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
agents/modules_meshcore/amt-mei.js
+82
-8
@@ -23,15 +23,18 @@ function amt_heci() {
23
24
this._ObjectID = "pthi";
25
this._rq = new Q();
26
- this._setupPTHI = function _setupPTHI() {
26
+ this._setupPTHI = function _setupPTHI()
27
+ {
28
this._amt = heci.create();
29
this._amt.BiosVersionLen = 65;
30
this._amt.UnicodeStringLen = 20;
31
32
this._amt.Parent = this;
33
this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); });
33
- this._amt.on('connect', function _amtOnConnect() {
34
- this.on('data', function _amtOnData(chunk) {
34
+ this._amt.on('connect', function _amtOnConnect()
35
+ {
36
+ this.on('data', function _amtOnData(chunk)
37
+ {
38
//console.log("Received: " + chunk.length + " bytes");
39
var header = this.Parent.getCommand(chunk);
40
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
@@ -43,12 +46,14 @@ function amt_heci() {
46
params.unshift(header);
47
callback.apply(this.Parent, params);
48
46
- if (this.Parent._rq.isEmpty()) {
49
+ if(this.Parent._rq.isEmpty())
50
+ {
51
// No More Requests, we can close PTHI
52
this.Parent._amt.disconnect();
53
this.Parent._amt = null;
54
}
51
- else {
55
+ else
56
+ {
57
// Send the next request
58
this.write(this.Parent._rq.peekQueue().send);
59
}
@@ -73,9 +78,10 @@ function amt_heci() {
78
var header = Buffer.from('010100000000000000000000', 'hex');
79
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
80
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
76
- this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args, send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]])) });
81
+ this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args , send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]]))});
82
78
- if (!this._amt) {
83
+ if(!this._amt)
84
+ {
85
this._setupPTHI();
86
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
87
}
@@ -87,7 +93,7 @@ function amt_heci() {
93
this.sendCommand(26, null, function (header, fn, opt) {
94
if (header.Status == 0) {
95
var i, CodeVersion = header.Data, val = { BiosVersion: CodeVersion.slice(0, this._amt.BiosVersionLen), Versions: [] }, v = CodeVersion.slice(this._amt.BiosVersionLen + 4);
90
- for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen); ++i) {
96
+ for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen) ; ++i) {
97
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() };
98
v = v.slice(4 + (2 * this._amt.UnicodeStringLen));
99
}
@@ -99,6 +105,34 @@ function amt_heci() {
105
}, callback, optional);
106
};
107
108
+ // Fill the left with zeros until the string is of a given length
109
+ function zeroLeftPad(str, len) {
110
+ if ((len == null) && (typeof (len) != 'number')) { return null; }
111
+ if (str == null) str = ''; // If null, this is to generate zero leftpad string
112
+ var zlp = '';
113
+ for (var i = 0; i < len - str.length; i++) { zlp += '0'; }
114
+ return zlp + str;
115
+ }
116
+
117
+ this.getUuid = function getUuid(callback) {
118
+ var optional = [];
119
+ for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
120
+ this.sendCommand(0x5c, null, function (header, fn, opt) {
121
+ if (header.Status == 0) {
122
+ var result = {};
123
+ result.uuid = [zeroLeftPad(header.Data.readUInt32LE(0).toString(16), 8),
124
+ zeroLeftPad(header.Data.readUInt16LE(4).toString(16), 4),
125
+ zeroLeftPad(header.Data.readUInt16LE(6).toString(16), 4),
126
+ zeroLeftPad(header.Data.readUInt16BE(8).toString(16), 4),
127
+ zeroLeftPad(header.Data.slice(10).toString('hex').toLowerCase(), 12)].join('-');
128
+ opt.unshift(result);
129
+ } else {
130
+ opt.unshift(null);
131
+ }
132
+ fn.apply(this, opt);
133
+ }, callback, optional);
134
+ };
135
+
136
this.getProvisioningState = function getProvisioningState(callback) {
137
var optional = [];
138
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
@@ -248,6 +282,46 @@ function amt_heci() {
282
fn.apply(this, opt);
283
}, callback, optional);
284
}
285
+ this.getLanInterfaceSettings = function getLanInterfaceSettings(index, callback)
286
+ {
287
+ var optional = [];
288
+ for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
289
+ var ifx = Buffer.alloc(4);
290
+ ifx.writeUInt32LE(index);
291
+ this.sendCommand(0x48, ifx, function onGetLanInterfaceSettings(header, fn, opt)
292
+ {
293
+ if(header.Status == 0)
294
+ {
295
+ var info = {};
296
+ info.enabled = header.Data.readUInt32LE(0);
297
+ info.dhcpEnabled = header.Data.readUInt32LE(8);
298
+ switch(header.Data[12])
299
+ {
300
+ case 1:
301
+ info.dhcpMode = 'ACTIVE'
302
+ break;
303
+ case 2:
304
+ info.dhcpMode = 'PASSIVE'
305
+ break;
306
+ default:
307
+ info.dhcpMode = 'UNKNOWN';
308
+ break;
309
+ }
310
+ info.mac = header.Data.slice(14).toString('hex:');
311
+
312
+ var addr = header.Data.readUInt32LE(4);
313
+ info.address = ((addr >> 24) & 255) + '.' + ((addr >> 16) & 255) + '.' + ((addr >> 8) & 255) + '.' + (addr & 255);
314
+ opt.unshift(info);
315
+ fn.apply(this, opt);
316
+ }
317
+ else
318
+ {
319
+ opt.unshift(null);
320
+ fn.apply(this, opt);
321
+ }
322
+ }, callback, optional);
323
+
324
+ };
325
this.unprovision = function unprovision(mode, callback) {
326
var optional = [];
327
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
db.js
+1
@@ -107,6 +107,7 @@ module.exports.CreateDB = function (args, datapath) {
107
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 }); }
108
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); } }
109
obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); }
110
+ obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); }
111
112
// 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.
113
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 }); }); }
meshagent.js
+1
@@ -549,6 +549,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
549
if (device.intelamt.state != command.intelamt.state) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); }
550
if (device.intelamt.flags != command.intelamt.flags) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); }
551
if (device.intelamt.host != command.intelamt.host) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); }
552
+ if (device.intelamt.uuid != command.intelamt.uuid) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); }
553
}
554
if (mesh.mtype == 2) {
555
if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); }
meshcentral.js
+1
@@ -227,6 +227,7 @@ function CreateMeshCentralServer(config, args) {
227
//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); }
228
229
// Look at passed in arguments
230
+ if ((obj.args.user != null) && (typeof obj.args.user != 'string')) { delete obj.args.user; }
231
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."); }
232
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; }
233
if (obj.args.port == null || typeof obj.args.port != 'number') { if (obj.args.notls == null) { obj.args.port = 443; } else { obj.args.port = 80; } }
meshrelay.js
+1
-1
@@ -69,7 +69,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
69
obj.parent.authenticate(req.query.user, req.query.pass, obj.domain, function (err, userid, passhint) {
70
if (userid != null) {
71
obj.authenticated = true;
72
- // Check is we have agent routing instructions, process this here.
72
+ // Check if we have agent routing instructions, process this here.
73
if ((req.query.nodeid != null) && (req.query.tcpport != null)) {
74
if (obj.id == undefined) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one.
75
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) };
meshuser.js
+3
-3
@@ -167,7 +167,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
167
case 'files':
168
{
169
// Send the full list of server files to the browser app
170
- if ((user.siteadmin & 8) != 0) { updateUserFiles(user, ws, domain); }
170
+ if ((user != null) && (user.siteadmin != null) && (user.siteadmin & 8) != 0) { updateUserFiles(user, ws, domain); }
171
break;
172
}
173
case 'fileoperation':
@@ -205,7 +205,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
205
if (agent != null) {
206
// Check if we have permission to send a message to that node
207
var rights = user.links[agent.dbMeshKey];
208
- if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
208
+ if ((rights != null) && ((rights.rights & 8) != 0)) { // 8 is remote control permission
209
command.sessionid = ws.sessionId; // Set the session id, required for responses.
210
command.rights = rights.rights; // Add user rights flags to the message
211
delete command.nodeid; // Remove the nodeid since it's implyed.
@@ -217,7 +217,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
217
if (routing != null) {
218
// Check if we have permission to send a message to that node
219
var rights = user.links[routing.meshid];
220
- if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
220
+ if ((rights != null) && ((rights.rights & 8) != 0)) { // 8 is remote control permission
221
command.fromSessionid = ws.sessionId; // Set the session id, required for responses.
222
command.rights = rights.rights; // Add user rights flags to the message
223
obj.parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid);
mpsserver.js
+61
-30
@@ -227,44 +227,75 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
227
obj.db.GetAllType('mesh', function (err, docs) {
228
var mesh = null;
229
for (var i in docs) { if (docs[i]._id.indexOf(meshIdStart) > 0) { mesh = docs[i]; break; } }
230
- if (mesh == null) { Debug(1, 'MPS:Mesh not found', username, password);SendUserAuthFail(socket); return -1; }
231
-
232
- // Intel AMT GUID (socket.tag.SystemId) will be used at NodeID
233
- var systemid = socket.tag.SystemId.split('-').join('');
234
- var nodeid = new Buffer(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
235
- socket.tag.name = '';
236
- socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
237
- socket.tag.meshid = mesh._id;
238
-
239
- obj.db.Get(socket.tag.nodeid, function (err, nodes) {
240
- if (nodes.length == 0) {
241
- if (mesh.mtype == 1) {
242
- // Node is not in the database, add it. Credentials will be empty until added by the user.
243
- 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 } };
244
- obj.db.Set(device);
245
-
246
- // Event the new node
247
- var device2 = common.Clone(device);
248
- if (device2.intelamt.pass != undefined) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
249
- var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name;
250
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain })
230
+ if (mesh == null) { Debug(1, 'MPS:Mesh not found', username, password); SendUserAuthFail(socket); return -1; }
231
+
232
+ // If this is a agent-less mesh, use the device guid 3 times as ID.
233
+ if (mesh.mtype == 1) {
234
+ // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
235
+ var systemid = socket.tag.SystemId.split('-').join('');
236
+ var nodeid = new Buffer(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
237
+ socket.tag.name = '';
238
+ socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
239
+ socket.tag.meshid = mesh._id;
240
+ socket.tag.connectTime = Date.now();
241
+
242
+ obj.db.Get(socket.tag.nodeid, function (err, nodes) {
243
+ if (nodes.length == 0) {
244
+ if (mesh.mtype == 1) {
245
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
246
+ 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 } };
247
+ obj.db.Set(device);
248
+
249
+ // Event the new node
250
+ var device2 = common.Clone(device);
251
+ if (device2.intelamt.pass != undefined) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
252
+ var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name;
253
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain })
254
+ } else {
255
+ // New CIRA connection for unknown node, disconnect.
256
+ console.log('CIRA connection for unknown node with incorrect mesh type. meshid: ' + socket.tag.meshid);
257
+ socket.end();
258
+ return;
259
+ }
260
} else {
261
+ // Node is already present
262
+ var node = nodes[0];
263
+ if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; }
264
+ }
265
+
266
+ // Add the connection to the MPS connection list
267
+ obj.ciraConnections[socket.tag.nodeid] = socket;
268
+ 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.
269
+ SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
270
+ });
271
+ } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID
272
+ // Intel AMT GUID (socket.tag.SystemId) will be used to search the node
273
+ obj.db.getAmtUuidNode(mesh._id, socket.tag.SystemId, function (err, nodes) {
274
+ if (nodes.length == 0) {
275
// New CIRA connection for unknown node, disconnect.
253
- console.log('CIRA connection for unknown node with incorrect mesh type. meshid: ' + socket.tag.meshid);
276
+ console.log('CIRA connection for unknown node. meshid: ' + mesh._id + ', uuid: ' + systemid);
277
socket.end();
278
return;
279
}
257
- } else {
258
- // Node is already present
280
+
281
+ // Node is present
282
var node = nodes[0];
283
if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; }
261
- }
284
+ socket.tag.nodeid = node._id;
285
+ socket.tag.meshid = mesh._id;
286
+ socket.tag.connectTime = Date.now();
287
263
- // Add the connection to the MPS connection list
264
- obj.ciraConnections[socket.tag.nodeid] = socket;
265
- 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.
266
- SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
267
- });
288
+ // Add the connection to the MPS connection list
289
+ obj.ciraConnections[socket.tag.nodeid] = socket;
290
+ 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.
291
+ SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
292
+ });
293
+ } else { // Unknown mesh type
294
+ // New CIRA connection for unknown node, disconnect.
295
+ console.log('CIRA connection to a unknown mesh type. meshid: ' + socket.tag.meshid);
296
+ socket.end();
297
+ return;
298
+ }
299
});
300
return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen;
301
}
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.1.5-e",
3
+ "version": "0.1.5-k",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
public/scripts/agent-desktop-0.0.2.js
+1
-1
@@ -159,7 +159,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
159
}
160
161
obj.ProcessScreenMsg = function (width, height) {
162
- //obj.Debug("ProcessScreenMsg: " + width + " x " + height);
162
+ obj.Debug("ScreenSize: " + width + " x " + height);
163
obj.Canvas.setTransform(1, 0, 0, 1, 0, 0);
164
obj.rotation = 0;
165
obj.FirstDraw = true;
views/default.handlebars
+16
-11
@@ -1468,10 +1468,10 @@
1468
function getMeshActions(mesh, meshrights) {
1469
if ((meshrights & 4) == 0) return '';
1470
var r = '';
1471
+ if ((features & 2) == 0) { // If not LAN-Only
1472
+ r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel® AMT computer that is located on the internet." onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
1473
+ }
1474
if (mesh.mtype == 1) {
1472
- if ((features & 2) == 0) { // If not LAN-Only
1473
- r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel® AMT computer that is located on the internet." onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
1474
- }
1475
if ((features & 1) == 0) { // If not WAN-Only
1476
r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel® AMT computer that is located on the local network." onclick=addDeviceToMesh(\"' + mesh._id + '\")>Add Local</a>';
1477
r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel® AMT computer by scanning the local network." onclick=addAmtScanToMesh(\"' + mesh._id + '\")>Scan Network</a>';
@@ -2580,7 +2580,7 @@
2580
if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '") title="Show device network interface information">Interfaces</a> ';
2581
if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '") title="Show device locations information">Location</a> ';
2582
2583
- if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showMeshCmdDialog(1,"' + node._id + '") title="Traffic router used to connect to a device thru this server.">Router</a> ';
2583
+ if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a style=cursor:pointer onclick=p10showMeshCmdDialog(1,"' + node._id + '") title="Traffic router used to connect to a device thru this server.">Router</a> ';
2584
2585
// RDP link, show this link only of the remote machine is Windows.
2586
if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
@@ -2616,11 +2616,11 @@
2616
// Show or hide the tabs
2617
// mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
2618
// node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
2619
- QV('MainDevDesktop', (mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0));
2620
- QV('MainDevTerminal', (mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0));
2621
- QV('MainDevFiles', (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0)));
2622
- QV('MainDevAmt', node.intelamt != null);
2623
- QV('MainDevConsole', consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0)));
2619
+ QV('MainDevDesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0)) && (meshrights & 8));
2620
+ QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0)) && (meshrights & 8));
2621
+ QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8));
2622
+ QV('MainDevAmt', (node.intelamt != null) && (meshrights & 8));
2623
+ QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
2624
QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0) && (userinfo.siteadmin == 0xFFFFFFFF));
2625
QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
2626
@@ -4041,8 +4041,12 @@
4041
c++;
4042
count++;
4043
4044
- // Mesh
4045
- var rights = 'Administrator'; // TODO
4044
+ // Mesh rights
4045
+ var meshrights = meshes[i].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
4046
+ var rights = 'Partial Rights';
4047
+ if (meshrights == 0xFFFFFFFF) rights = 'Full Administrator'; else if (meshrights == 0) rights = 'No Rights';
4048
+
4049
+ // Print the mesh information
4050
r += '<div style=display:inline-block;width:431px;height:50px;padding-top:1px;padding-bottom:1px;float:left><div style=float:left;width:30px;height:100%></div><div style=height:100%;cursor:pointer onclick=gotoMesh(\'' + i + '\')><div class=mi style=float:left;width:50px;height:50px></div><div style=height:100%><div class=g1></div><div class=e2 style=width:300px><div class=e1>' + EscapeHtml(meshes[i].name) + '</div><div>' + rights + '</div></div><div class=g2 style=float:left></div></div></div></div>';
4051
}
4052
@@ -4247,6 +4251,7 @@
4251
if ((meshrights & 64) != 0) r += ', Wake Devices';
4252
}
4253
r = r.substring(2);
4254
+ if (r == '') { r = 'No Rights'; }
4255
var x = addHtmlValue('User Name', userid.split('/')[2]);
4256
x += addHtmlValue('Permissions', r);
4257
var buttons = 1;
webserver.js
+16
@@ -537,6 +537,22 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
537
obj.authenticate(user.name, req.body.apassword1, domain, function (err, userid) {
538
var user = obj.users[userid];
539
if (user) {
540
+ // Remove all the mesh links to this user
541
+ if (user.links != null) {
542
+ for (var meshid in user.links) {
543
+ // Get the mesh
544
+ var mesh = obj.meshes[meshid];
545
+ if (mesh) {
546
+ // Remove user from the mesh
547
+ if (mesh.links[userid] != null) { delete mesh.links[userid]; obj.db.Set(mesh); }
548
+ // Notify mesh change
549
+ var change = 'Removed user ' + user.name + ' from mesh ' + mesh.name;
550
+ obj.parent.DispatchEvent(['*', mesh._id, user._id, userid], obj, { etype: 'mesh', username: user.name, userid: userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id })
551
+ }
552
+ }
553
+ }
554
+
555
+ // Remove the user
556
obj.db.Remove(user._id);
557
delete obj.users[user._id];
558
req.session.destroy(function () { res.redirect(domain.url); });