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