Mesh agents can now connect and skip server cert check to boost speed
Ylian Saint-Hilaire committed
Aug 21, 2018 at 15:08 UTC
82801f40691735de31e6026ea3ffe267daa8db70
9 files changed
+230
-229
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
meshagent.js
+187
-182
@@ -185,18 +185,23 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
185
186
// Use our server private key to sign the ServerHash + AgentNonce + ServerNonce
187
obj.agentnonce = msg.substring(50);
188
- if (obj.useSwarmCert == true) {
189
- // Perform the hash signature using older swarm server certificate
190
- obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
191
- // Send back our certificate + signature
192
- obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.parent.swarmCertificateAsn1.length) + obj2.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
193
- });
194
- } else {
195
- // Perform the hash signature using the server agent certificate
196
- obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
197
- // Send back our certificate + signature
198
- obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.parent.agentCertificateAsn1.length) + obj2.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
199
- });
188
+
189
+ // Check if we got the agent auth confirmation
190
+ if ((obj.receivedCommands & 8) == 0) {
191
+ // If we did not get an indication that the agent already validated this server, send the server signature.
192
+ if (obj.useSwarmCert == true) {
193
+ // Perform the hash signature using older swarm server certificate
194
+ obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
195
+ // Send back our certificate + signature
196
+ obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.parent.swarmCertificateAsn1.length) + obj2.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
197
+ });
198
+ } else {
199
+ // Perform the hash signature using the server agent certificate
200
+ obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
201
+ // Send back our certificate + signature
202
+ obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.parent.agentCertificateAsn1.length) + obj2.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
203
+ });
204
+ }
205
}
206
207
// Check the agent signature if we can
@@ -242,6 +247,10 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
247
obj.agentInfo.computerName = msg.substring(72, 72 + computerNameLen);
248
obj.dbMeshKey = 'mesh/' + obj.domain.id + '/' + obj.meshid;
249
completeAgentConnection();
250
+ } else if (cmd == 4) {
251
+ if ((msg.length < 2) || ((obj.receivedCommands & 8) != 0)) return;
252
+ obj.receivedCommands += 8; // Agent can't send the same command twice on the same connection ever. Block DOS attack path.
253
+ // Agent already authenticated the server, wants to skip the server signature - which is great for server performance.
254
} else if (cmd == 5) {
255
// ServerID. Agent is telling us what serverid it expects. Useful if we have many server certificates.
256
if ((msg.substring(2, 34) == obj.parent.swarmCertificateHash256) || (msg.substring(2, 50) == obj.parent.swarmCertificateHash384)) { obj.useSwarmCert = true; }
@@ -263,127 +272,125 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
272
273
// Once we get all the information about an agent, run this to hook everything up to the server
274
function completeAgentConnection() {
266
- if (obj.authenticated = !1 || obj.meshid == null || obj.pendingCompleteAgentConnection) return;
275
+ if ((obj.authenticated != 1) || (obj.meshid == null) || obj.pendingCompleteAgentConnection) return;
276
obj.pendingCompleteAgentConnection = true;
277
278
// Check that the mesh exists
270
- obj.db.Get(obj.dbMeshKey, function (err, meshes) {
271
- if (meshes.length == 0) { console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddr + ', ' + obj.dbMeshKey + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
272
- var mesh = meshes[0];
273
- if (mesh.mtype != 2) { console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddr + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
274
-
275
- // Check that the node exists
276
- obj.db.Get(obj.dbNodeKey, function (err, nodes) {
277
- var device;
278
-
279
- // Mark when we connected to this agent
280
- obj.connectTime = Date.now();
281
- if (nodes.length == 0) {
282
- // This node does not exist, create it.
283
- device = { type: 'node', mtype: mesh.mtype, _id: obj.dbNodeKey, icon: obj.agentInfo.platformType, meshid: obj.dbMeshKey, name: obj.agentInfo.computerName, rname: obj.agentInfo.computerName, domain: domain.id, agent: { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }, host: null };
284
- obj.db.Set(device);
279
+ var mesh = obj.parent.meshes[obj.dbMeshKey];
280
+ if (mesh == null) { console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddr + ', ' + obj.dbMeshKey + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
281
+ if (mesh.mtype != 2) { console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddr + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
282
286
- // Event the new node
287
- if (obj.agentInfo.capabilities & 0x20) {
288
- // This is a temporary agent, don't log.
289
- obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 })
290
- } else {
291
- var change = 'Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name;
292
- obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: change, domain: domain.id })
293
- }
283
+ // Check that the node exists
284
+ obj.db.Get(obj.dbNodeKey, function (err, nodes) {
285
+ var device;
286
+
287
+ // Mark when we connected to this agent
288
+ obj.connectTime = Date.now();
289
+ if (nodes.length == 0) {
290
+ // This node does not exist, create it.
291
+ device = { type: 'node', mtype: mesh.mtype, _id: obj.dbNodeKey, icon: obj.agentInfo.platformType, meshid: obj.dbMeshKey, name: obj.agentInfo.computerName, rname: obj.agentInfo.computerName, domain: domain.id, agent: { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }, host: null };
292
+ obj.db.Set(device);
293
+
294
+ // Event the new node
295
+ if (obj.agentInfo.capabilities & 0x20) {
296
+ // This is a temporary agent, don't log.
297
+ obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 })
298
} else {
295
- // Device already exists, look if changes has occured
296
- device = nodes[0];
297
- if (device.agent == null) {
298
- device.agent = { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }; change = 1;
299
- } else {
300
- var changes = [], change = 0, log = 0;
301
- if (device.rname != obj.agentInfo.computerName) { device.rname = obj.agentInfo.computerName; change = 1; changes.push('computer name'); }
302
- if (device.agent.ver != obj.agentInfo.agentVersion) { device.agent.ver = obj.agentInfo.agentVersion; change = 1; changes.push('agent version'); }
303
- if (device.agent.id != obj.agentInfo.agentId) { device.agent.id = obj.agentInfo.agentId; change = 1; changes.push('agent type'); }
304
- if ((device.agent.caps & 24) != (obj.agentInfo.capabilities & 24)) { device.agent.caps = obj.agentInfo.capabilities; change = 1; changes.push('agent capabilities'); } // If agent console or javascript support changes, update capabilities
305
- if (device.meshid != obj.dbMeshKey) { device.meshid = obj.dbMeshKey; change = 1; log = 1; changes.push('agent meshid'); } // TODO: If the meshid changes, we need to event a device add/remove on both meshes
306
- if (change == 1) {
307
- obj.db.Set(device);
308
-
309
- // If this is a temporary device, don't log changes
310
- if (obj.agentInfo.capabilities & 0x20) { log = 0; }
311
-
312
- // Event the node change
313
- var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id };
314
- if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); }
315
- var device2 = obj.common.Clone(device);
316
- if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
317
- event.node = device;
318
- obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
319
- }
320
- }
299
+ var change = 'Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name;
300
+ obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: change, domain: domain.id })
301
}
322
-
323
- // Check if this agent is already connected
324
- var dupAgent = obj.parent.wsagents[obj.dbNodeKey];
325
- obj.parent.wsagents[obj.dbNodeKey] = obj;
326
- if (dupAgent) {
327
- // Close the duplicate agent
328
- if (obj.nodeid != null) { obj.parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddr + ')'); }
329
- dupAgent.close(3);
302
+ } else {
303
+ // Device already exists, look if changes has occured
304
+ device = nodes[0];
305
+ if (device.agent == null) {
306
+ device.agent = { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }; change = 1;
307
} else {
331
- // Indicate the agent is connected
332
- obj.parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1);
333
- }
334
-
335
- // We are done, ready to communicate with this agent
336
- delete obj.pendingCompleteAgentConnection;
337
- obj.authenticated = 2;
308
+ var changes = [], change = 0, log = 0;
309
+ if (device.rname != obj.agentInfo.computerName) { device.rname = obj.agentInfo.computerName; change = 1; changes.push('computer name'); }
310
+ if (device.agent.ver != obj.agentInfo.agentVersion) { device.agent.ver = obj.agentInfo.agentVersion; change = 1; changes.push('agent version'); }
311
+ if (device.agent.id != obj.agentInfo.agentId) { device.agent.id = obj.agentInfo.agentId; change = 1; changes.push('agent type'); }
312
+ if ((device.agent.caps & 24) != (obj.agentInfo.capabilities & 24)) { device.agent.caps = obj.agentInfo.capabilities; change = 1; changes.push('agent capabilities'); } // If agent console or javascript support changes, update capabilities
313
+ if (device.meshid != obj.dbMeshKey) { device.meshid = obj.dbMeshKey; change = 1; log = 1; changes.push('agent meshid'); } // TODO: If the meshid changes, we need to event a device add/remove on both meshes
314
+ if (change == 1) {
315
+ obj.db.Set(device);
316
339
- // Command 4, inform mesh agent that it's authenticated.
340
- obj.send(obj.common.ShortToStr(4));
317
+ // If this is a temporary device, don't log changes
318
+ if (obj.agentInfo.capabilities & 0x20) { log = 0; }
319
342
- // Check the mesh core, if the agent is capable of running one
343
- if ((obj.agentInfo.capabilities & 16) != 0) { obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); } // Command 11, ask for mesh core hash.
320
+ // Event the node change
321
+ var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id };
322
+ if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); }
323
+ var device2 = obj.common.Clone(device);
324
+ if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
325
+ event.node = device;
326
+ obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
327
+ }
328
+ }
329
+ }
330
345
- // Check if we need to make an native update check
346
- obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
347
- if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) { obj.send(obj.common.ShortToStr(12) + obj.common.ShortToStr(0)); } // Ask the agent for it's executable binary hash
331
+ // Check if this agent is already connected
332
+ var dupAgent = obj.parent.wsagents[obj.dbNodeKey];
333
+ obj.parent.wsagents[obj.dbNodeKey] = obj;
334
+ if (dupAgent) {
335
+ // Close the duplicate agent
336
+ if (obj.nodeid != null) { obj.parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddr + ')'); }
337
+ dupAgent.close(3);
338
+ } else {
339
+ // Indicate the agent is connected
340
+ obj.parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1);
341
+ }
342
349
- // Check if we already have IP location information for this node
350
- obj.db.Get('iploc_' + obj.remoteaddr, function (err, iplocs) {
351
- if (iplocs.length == 1) {
352
- // We have a location in the database for this remote IP
353
- var iploc = nodes[0], x = {};
354
- if ((iploc != null) && (iploc.ip != null) && (iploc.loc != null)) {
355
- x.publicip = iploc.ip;
356
- x.iploc = iploc.loc + ',' + (Math.floor((new Date(iploc.date)) / 1000));
357
- ChangeAgentLocationInfo(x);
358
- }
343
+ // We are done, ready to communicate with this agent
344
+ delete obj.pendingCompleteAgentConnection;
345
+ obj.authenticated = 2;
346
+
347
+ // Command 4, inform mesh agent that it's authenticated.
348
+ obj.send(obj.common.ShortToStr(4));
349
+
350
+ // Check the mesh core, if the agent is capable of running one
351
+ if ((obj.agentInfo.capabilities & 16) != 0) { obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); } // Command 11, ask for mesh core hash.
352
+
353
+ // Check if we need to make an native update check
354
+ obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
355
+ if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) { obj.send(obj.common.ShortToStr(12) + obj.common.ShortToStr(0)); } // Ask the agent for it's executable binary hash
356
+
357
+ // Check if we already have IP location information for this node
358
+ obj.db.Get('iploc_' + obj.remoteaddr, function (err, iplocs) {
359
+ if (iplocs.length == 1) {
360
+ // We have a location in the database for this remote IP
361
+ var iploc = nodes[0], x = {};
362
+ if ((iploc != null) && (iploc.ip != null) && (iploc.loc != null)) {
363
+ x.publicip = iploc.ip;
364
+ x.iploc = iploc.loc + ',' + (Math.floor((new Date(iploc.date)) / 1000));
365
+ ChangeAgentLocationInfo(x);
366
+ }
367
+ } else {
368
+ // Check if we need to ask for the IP location
369
+ var doIpLocation = 0;
370
+ if (device.iploc == null) {
371
+ doIpLocation = 1;
372
} else {
360
- // Check if we need to ask for the IP location
361
- var doIpLocation = 0;
362
- if (device.iploc == null) {
363
- doIpLocation = 1;
373
+ var loc = device.iploc.split(',');
374
+ if (loc.length < 3) {
375
+ doIpLocation = 2;
376
} else {
365
- var loc = device.iploc.split(',');
366
- if (loc.length < 3) {
367
- doIpLocation = 2;
368
- } else {
369
- var t = new Date((parseFloat(loc[2]) * 1000)), now = Date.now();
370
- t.setDate(t.getDate() + 20);
371
- if (t < now) { doIpLocation = 3; }
372
- }
377
+ var t = new Date((parseFloat(loc[2]) * 1000)), now = Date.now();
378
+ t.setDate(t.getDate() + 20);
379
+ if (t < now) { doIpLocation = 3; }
380
}
381
+ }
382
375
- // If we need to ask for IP location, see if we have the quota to do it.
376
- if (doIpLocation > 0) {
377
- obj.db.getValueOfTheDay('ipLocationRequestLimitor', 10, function (ipLocationLimitor) {
378
- if (ipLocationLimitor.value > 0) {
379
- ipLocationLimitor.value--;
380
- obj.db.Set(ipLocationLimitor);
381
- obj.send(JSON.stringify({ action: 'iplocation' }));
382
- }
383
- });
384
- }
383
+ // If we need to ask for IP location, see if we have the quota to do it.
384
+ if (doIpLocation > 0) {
385
+ obj.db.getValueOfTheDay('ipLocationRequestLimitor', 10, function (ipLocationLimitor) {
386
+ if (ipLocationLimitor.value > 0) {
387
+ ipLocationLimitor.value--;
388
+ obj.db.Set(ipLocationLimitor);
389
+ obj.send(JSON.stringify({ action: 'iplocation' }));
390
+ }
391
+ });
392
}
386
- });
393
+ }
394
});
395
});
396
}
@@ -566,83 +573,81 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
573
if (command.caps == null || command.caps == null) { command.caps = 0; } else { if (typeof command.caps != 'number') command.caps = 0; }
574
575
// Check that the mesh exists
569
- obj.db.Get(obj.dbMeshKey, function (err, meshes) {
570
- if (meshes.length != 1) return;
571
- var mesh = meshes[0];
572
- // Get the node and change it if needed
573
- obj.db.Get(obj.dbNodeKey, function (err, nodes) {
574
- if (nodes.length != 1) return;
575
- var device = nodes[0];
576
- if (device.agent) {
577
- var changes = [], change = 0;
578
-
579
- // Check if anything changes
580
- if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); }
581
- if (device.agent.core != command.value) { if ((command.value == null) && (device.agent.core != null)) { delete device.agent.core; } else { device.agent.core = command.value; } change = 1; changes.push('agent core'); }
582
- if ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7)) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; changes.push('agent capabilities'); } // Allow Javascript on the agent to change all capabilities except console and javascript support
583
- if (command.intelamt) {
584
- if (!device.intelamt) { device.intelamt = {}; }
585
- if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { device.intelamt.ver = command.intelamt.ver; change = 1; changes.push('AMT version'); }
586
- if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); }
587
- if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); }
588
- if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); }
589
- if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); }
590
- }
591
- if (mesh.mtype == 2) {
592
- if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); }
593
- // TODO: Check that the agent has an interface that is the same as the one we got this websocket connection on. Only set if we have a match.
594
- }
576
+ var mesh = obj.parent.meshes[obj.dbMeshKey];
577
+ if (mesh == null) return;
578
596
- // If there are changes, save and event
597
- if (change == 1) {
598
- obj.db.Set(device);
579
+ // Get the node and change it if needed
580
+ obj.db.Get(obj.dbNodeKey, function (err, nodes) {
581
+ if (nodes.length != 1) return;
582
+ var device = nodes[0];
583
+ if (device.agent) {
584
+ var changes = [], change = 0;
585
+
586
+ // Check if anything changes
587
+ if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); }
588
+ if (device.agent.core != command.value) { if ((command.value == null) && (device.agent.core != null)) { delete device.agent.core; } else { device.agent.core = command.value; } change = 1; changes.push('agent core'); }
589
+ if ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7)) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; changes.push('agent capabilities'); } // Allow Javascript on the agent to change all capabilities except console and javascript support
590
+ if (command.intelamt) {
591
+ if (!device.intelamt) { device.intelamt = {}; }
592
+ if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { device.intelamt.ver = command.intelamt.ver; change = 1; changes.push('AMT version'); }
593
+ if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); }
594
+ if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); }
595
+ if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); }
596
+ if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); }
597
+ }
598
+ if (mesh.mtype == 2) {
599
+ if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); }
600
+ // TODO: Check that the agent has an interface that is the same as the one we got this websocket connection on. Only set if we have a match.
601
+ }
602
600
- // Event the node change
601
- var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
602
- if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
603
- var device2 = obj.common.Clone(device);
604
- if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
605
- event.node = device;
606
- obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
607
- }
603
+ // If there are changes, save and event
604
+ if (change == 1) {
605
+ obj.db.Set(device);
606
+
607
+ // Event the node change
608
+ var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
609
+ if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
610
+ var device2 = obj.common.Clone(device);
611
+ if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
612
+ event.node = device;
613
+ obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
614
}
609
- });
615
+ }
616
});
617
}
618
619
// Change the current core information string and event it
620
function ChangeAgentLocationInfo(command) {
615
- if ((command == null) || (command == null)) return; // Safety, should never happen.
621
+ if ((command == null) || (command == null)) { return; } // Safety, should never happen.
622
623
// Check that the mesh exists
618
- obj.db.Get(obj.dbMeshKey, function (err, meshes) {
619
- if (meshes.length != 1) return;
620
- var mesh = meshes[0];
621
- // Get the node and change it if needed
622
- obj.db.Get(obj.dbNodeKey, function (err, nodes) {
623
- if (nodes.length != 1) return;
624
- var device = nodes[0];
625
- if (device.agent) {
626
- var changes = [], change = 0;
627
-
628
- // Check if anything changes
629
- if ((command.publicip) && (device.publicip != command.publicip)) { device.publicip = command.publicip; change = 1; changes.push('public ip'); }
630
- if ((command.iploc) && (device.iploc != command.iploc)) { device.iploc = command.iploc; change = 1; changes.push('ip location'); }
631
-
632
- // If there are changes, save and event
633
- if (change == 1) {
634
- obj.db.Set(device);
624
+ var mesh = obj.parent.meshes[obj.dbMeshKey];
625
+ if (mesh == null) return;
626
636
- // Event the node change
637
- var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
638
- if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
639
- var device2 = obj.common.Clone(device);
640
- if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
641
- event.node = device;
642
- obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
643
- }
627
+ // Get the node and change it if needed
628
+ obj.db.Get(obj.dbNodeKey, function (err, nodes) {
629
+ if (nodes.length != 1) { return; }
630
+ var device = nodes[0];
631
+ if (device.agent) {
632
+ var changes = [], change = 0;
633
+
634
+ // Check if anything changes
635
+ if ((command.publicip) && (device.publicip != command.publicip)) { device.publicip = command.publicip; change = 1; changes.push('public ip'); }
636
+ if ((command.iploc) && (device.iploc != command.iploc)) { device.iploc = command.iploc; change = 1; changes.push('ip location'); }
637
+
638
+ // If there are changes, save and event
639
+ if (change == 1) {
640
+ obj.db.Set(device);
641
+
642
+ // Event the node change
643
+ var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
644
+ if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
645
+ var device2 = obj.common.Clone(device);
646
+ if (device2.intelamt && device2.intelamt.pass) { delete device2.intelamt.pass; } // Remove the Intel AMT password before eventing this.
647
+ event.node = device;
648
+ obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
649
}
645
- });
650
+ }
651
});
652
}
653
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.1.9-j",
3
+ "version": "0.1.9-k",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
webserver.js
+42
-46
@@ -1468,32 +1468,30 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
1468
res.sendFile(argentInfo.path);
1469
} else {
1470
// We are going to embed the .msh file into the Windows executable (signed or not).
1471
- // First, query the meshid to build the .msh file
1472
- obj.db.Get('mesh/' + domain.id + '/' + req.query.meshid, function (err, meshes) {
1473
- if (meshes.length != 1) { res.sendStatus(401); return; }
1474
- var mesh = meshes[0];
1475
-
1476
- // If required, check if this user has rights to do this
1477
- if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
1478
- var user = obj.users[req.session.userid];
1479
- var escUserId = obj.common.escapeFieldName(user._id);
1480
- if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
1481
- if (domain.id != mesh.domain) { res.sendStatus(401); return; }
1482
- }
1471
+ // First, fetch the mesh object to build the .msh file
1472
+ var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.meshid];
1473
+ if (mesh == null) { res.sendStatus(401); return; }
1474
+
1475
+ // If required, check if this user has rights to do this
1476
+ if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
1477
+ var user = obj.users[req.session.userid];
1478
+ var escUserId = obj.common.escapeFieldName(user._id);
1479
+ if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
1480
+ if (domain.id != mesh.domain) { res.sendStatus(401); return; }
1481
+ }
1482
1484
- var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1485
- var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1486
- var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
1483
+ var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1484
+ var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1485
+ var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
1486
1488
- // Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
1489
- var xdomain = (domain.dns == null) ? domain.id : '';
1490
- if (xdomain != '') xdomain += "/";
1491
- var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
1492
- if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
1493
- if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
1494
- res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + argentInfo.rname });
1495
- obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe });
1496
- });
1487
+ // Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
1488
+ var xdomain = (domain.dns == null) ? domain.id : '';
1489
+ if (xdomain != '') xdomain += "/";
1490
+ var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
1491
+ if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
1492
+ if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
1493
+ res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + argentInfo.rname });
1494
+ obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe });
1495
}
1496
} else if (req.query.script != null) {
1497
// Send a specific mesh install script back
@@ -1602,32 +1600,30 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
1600
// If required, check if this user has rights to do this
1601
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true) && (req.session.userid == null)) { res.sendStatus(401); return; }
1602
1605
- // Query the meshid
1606
- obj.db.Get('mesh/' + domain.id + '/' + req.query.id, function (err, meshes) {
1607
- if (meshes.length != 1) { res.sendStatus(401); return; }
1608
- var mesh = meshes[0];
1603
+ // Fetch the mesh object
1604
+ var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.id];
1605
+ if (mesh == null) { res.sendStatus(401); return; }
1606
1610
- // If needed, check if this user has rights to do this
1611
- if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
1612
- var user = obj.users[req.session.userid];
1613
- var escUserId = obj.common.escapeFieldName(user._id);
1614
- if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
1615
- if (domain.id != mesh.domain) { res.sendStatus(401); return; }
1616
- }
1607
+ // If needed, check if this user has rights to do this
1608
+ if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
1609
+ var user = obj.users[req.session.userid];
1610
+ var escUserId = obj.common.escapeFieldName(user._id);
1611
+ if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
1612
+ if (domain.id != mesh.domain) { res.sendStatus(401); return; }
1613
+ }
1614
1618
- var meshidhex = new Buffer(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1619
- var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1615
+ var meshidhex = new Buffer(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1616
+ var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
1617
1621
- // Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
1622
- var xdomain = (domain.dns == null) ? domain.id : '';
1623
- if (xdomain != '') xdomain += "/";
1624
- var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
1625
- var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
1626
- if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
1618
+ // Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
1619
+ var xdomain = (domain.dns == null) ? domain.id : '';
1620
+ if (xdomain != '') xdomain += "/";
1621
+ var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
1622
+ var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
1623
+ if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
1624
1628
- res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshagent.msh' });
1629
- res.send(meshsettings);
1630
- });
1625
+ res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshagent.msh' });
1626
+ res.send(meshsettings);
1627
}
1628
1629
// Add HTTP security headers to all responses