Mesh agents can now connect and skip server cert check to boost speed

This commit is contained in:
Ylian Saint-Hilaire 2018-08-21 15:08:15 -07:00
parent d3db0e4ef6
commit 82801f4069
9 changed files with 226 additions and 225 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -185,18 +185,23 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Use our server private key to sign the ServerHash + AgentNonce + ServerNonce
obj.agentnonce = msg.substring(50);
if (obj.useSwarmCert == true) {
// Perform the hash signature using older swarm server certificate
obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
// Send back our certificate + signature
obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.parent.swarmCertificateAsn1.length) + obj2.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
});
} else {
// Perform the hash signature using the server agent certificate
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
// Send back our certificate + signature
obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.parent.agentCertificateAsn1.length) + obj2.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
});
// Check if we got the agent auth confirmation
if ((obj.receivedCommands & 8) == 0) {
// If we did not get an indication that the agent already validated this server, send the server signature.
if (obj.useSwarmCert == true) {
// Perform the hash signature using older swarm server certificate
obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
// Send back our certificate + signature
obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.parent.swarmCertificateAsn1.length) + obj2.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
});
} else {
// Perform the hash signature using the server agent certificate
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
// Send back our certificate + signature
obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.parent.agentCertificateAsn1.length) + obj2.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
});
}
}
// Check the agent signature if we can
@ -242,6 +247,10 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
obj.agentInfo.computerName = msg.substring(72, 72 + computerNameLen);
obj.dbMeshKey = 'mesh/' + obj.domain.id + '/' + obj.meshid;
completeAgentConnection();
} else if (cmd == 4) {
if ((msg.length < 2) || ((obj.receivedCommands & 8) != 0)) return;
obj.receivedCommands += 8; // Agent can't send the same command twice on the same connection ever. Block DOS attack path.
// Agent already authenticated the server, wants to skip the server signature - which is great for server performance.
} else if (cmd == 5) {
// ServerID. Agent is telling us what serverid it expects. Useful if we have many server certificates.
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) {
// Once we get all the information about an agent, run this to hook everything up to the server
function completeAgentConnection() {
if (obj.authenticated = !1 || obj.meshid == null || obj.pendingCompleteAgentConnection) return;
if ((obj.authenticated != 1) || (obj.meshid == null) || obj.pendingCompleteAgentConnection) return;
obj.pendingCompleteAgentConnection = true;
// Check that the mesh exists
obj.db.Get(obj.dbMeshKey, function (err, meshes) {
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.
var mesh = meshes[0];
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.
var mesh = obj.parent.meshes[obj.dbMeshKey];
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.
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.
// Check that the node exists
obj.db.Get(obj.dbNodeKey, function (err, nodes) {
var device;
// Check that the node exists
obj.db.Get(obj.dbNodeKey, function (err, nodes) {
var device;
// Mark when we connected to this agent
obj.connectTime = Date.now();
if (nodes.length == 0) {
// This node does not exist, create it.
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 };
obj.db.Set(device);
// Mark when we connected to this agent
obj.connectTime = Date.now();
if (nodes.length == 0) {
// This node does not exist, create it.
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 };
obj.db.Set(device);
// Event the new node
if (obj.agentInfo.capabilities & 0x20) {
// This is a temporary agent, don't log.
obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 })
} else {
var change = 'Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name;
obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: change, domain: domain.id })
}
// Event the new node
if (obj.agentInfo.capabilities & 0x20) {
// This is a temporary agent, don't log.
obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 })
} else {
// Device already exists, look if changes has occured
device = nodes[0];
if (device.agent == null) {
device.agent = { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }; change = 1;
} else {
var changes = [], change = 0, log = 0;
if (device.rname != obj.agentInfo.computerName) { device.rname = obj.agentInfo.computerName; change = 1; changes.push('computer name'); }
if (device.agent.ver != obj.agentInfo.agentVersion) { device.agent.ver = obj.agentInfo.agentVersion; change = 1; changes.push('agent version'); }
if (device.agent.id != obj.agentInfo.agentId) { device.agent.id = obj.agentInfo.agentId; change = 1; changes.push('agent type'); }
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
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
if (change == 1) {
obj.db.Set(device);
var change = 'Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name;
obj.parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: change, domain: domain.id })
}
} else {
// Device already exists, look if changes has occured
device = nodes[0];
if (device.agent == null) {
device.agent = { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }; change = 1;
} else {
var changes = [], change = 0, log = 0;
if (device.rname != obj.agentInfo.computerName) { device.rname = obj.agentInfo.computerName; change = 1; changes.push('computer name'); }
if (device.agent.ver != obj.agentInfo.agentVersion) { device.agent.ver = obj.agentInfo.agentVersion; change = 1; changes.push('agent version'); }
if (device.agent.id != obj.agentInfo.agentId) { device.agent.id = obj.agentInfo.agentId; change = 1; changes.push('agent type'); }
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
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
if (change == 1) {
obj.db.Set(device);
// If this is a temporary device, don't log changes
if (obj.agentInfo.capabilities & 0x20) { log = 0; }
// If this is a temporary device, don't log changes
if (obj.agentInfo.capabilities & 0x20) { log = 0; }
// Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id };
if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); }
var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
event.node = device;
obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
}
// Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id };
if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); }
var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
event.node = device;
obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
}
}
}
// Check if this agent is already connected
var dupAgent = obj.parent.wsagents[obj.dbNodeKey];
obj.parent.wsagents[obj.dbNodeKey] = obj;
if (dupAgent) {
// Close the duplicate agent
if (obj.nodeid != null) { obj.parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddr + ')'); }
dupAgent.close(3);
// Check if this agent is already connected
var dupAgent = obj.parent.wsagents[obj.dbNodeKey];
obj.parent.wsagents[obj.dbNodeKey] = obj;
if (dupAgent) {
// Close the duplicate agent
if (obj.nodeid != null) { obj.parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddr + ')'); }
dupAgent.close(3);
} else {
// Indicate the agent is connected
obj.parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1);
}
// We are done, ready to communicate with this agent
delete obj.pendingCompleteAgentConnection;
obj.authenticated = 2;
// Command 4, inform mesh agent that it's authenticated.
obj.send(obj.common.ShortToStr(4));
// Check the mesh core, if the agent is capable of running one
if ((obj.agentInfo.capabilities & 16) != 0) { obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); } // Command 11, ask for mesh core hash.
// Check if we need to make an native update check
obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
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
// Check if we already have IP location information for this node
obj.db.Get('iploc_' + obj.remoteaddr, function (err, iplocs) {
if (iplocs.length == 1) {
// We have a location in the database for this remote IP
var iploc = nodes[0], x = {};
if ((iploc != null) && (iploc.ip != null) && (iploc.loc != null)) {
x.publicip = iploc.ip;
x.iploc = iploc.loc + ',' + (Math.floor((new Date(iploc.date)) / 1000));
ChangeAgentLocationInfo(x);
}
} else {
// Indicate the agent is connected
obj.parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1);
}
// We are done, ready to communicate with this agent
delete obj.pendingCompleteAgentConnection;
obj.authenticated = 2;
// Command 4, inform mesh agent that it's authenticated.
obj.send(obj.common.ShortToStr(4));
// Check the mesh core, if the agent is capable of running one
if ((obj.agentInfo.capabilities & 16) != 0) { obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); } // Command 11, ask for mesh core hash.
// Check if we need to make an native update check
obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
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
// Check if we already have IP location information for this node
obj.db.Get('iploc_' + obj.remoteaddr, function (err, iplocs) {
if (iplocs.length == 1) {
// We have a location in the database for this remote IP
var iploc = nodes[0], x = {};
if ((iploc != null) && (iploc.ip != null) && (iploc.loc != null)) {
x.publicip = iploc.ip;
x.iploc = iploc.loc + ',' + (Math.floor((new Date(iploc.date)) / 1000));
ChangeAgentLocationInfo(x);
}
// Check if we need to ask for the IP location
var doIpLocation = 0;
if (device.iploc == null) {
doIpLocation = 1;
} else {
// Check if we need to ask for the IP location
var doIpLocation = 0;
if (device.iploc == null) {
doIpLocation = 1;
var loc = device.iploc.split(',');
if (loc.length < 3) {
doIpLocation = 2;
} else {
var loc = device.iploc.split(',');
if (loc.length < 3) {
doIpLocation = 2;
} else {
var t = new Date((parseFloat(loc[2]) * 1000)), now = Date.now();
t.setDate(t.getDate() + 20);
if (t < now) { doIpLocation = 3; }
}
}
// If we need to ask for IP location, see if we have the quota to do it.
if (doIpLocation > 0) {
obj.db.getValueOfTheDay('ipLocationRequestLimitor', 10, function (ipLocationLimitor) {
if (ipLocationLimitor.value > 0) {
ipLocationLimitor.value--;
obj.db.Set(ipLocationLimitor);
obj.send(JSON.stringify({ action: 'iplocation' }));
}
});
var t = new Date((parseFloat(loc[2]) * 1000)), now = Date.now();
t.setDate(t.getDate() + 20);
if (t < now) { doIpLocation = 3; }
}
}
});
// If we need to ask for IP location, see if we have the quota to do it.
if (doIpLocation > 0) {
obj.db.getValueOfTheDay('ipLocationRequestLimitor', 10, function (ipLocationLimitor) {
if (ipLocationLimitor.value > 0) {
ipLocationLimitor.value--;
obj.db.Set(ipLocationLimitor);
obj.send(JSON.stringify({ action: 'iplocation' }));
}
});
}
}
});
});
}
@ -566,83 +573,81 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (command.caps == null || command.caps == null) { command.caps = 0; } else { if (typeof command.caps != 'number') command.caps = 0; }
// Check that the mesh exists
obj.db.Get(obj.dbMeshKey, function (err, meshes) {
if (meshes.length != 1) return;
var mesh = meshes[0];
// Get the node and change it if needed
obj.db.Get(obj.dbNodeKey, function (err, nodes) {
if (nodes.length != 1) return;
var device = nodes[0];
if (device.agent) {
var changes = [], change = 0;
var mesh = obj.parent.meshes[obj.dbMeshKey];
if (mesh == null) return;
// Check if anything changes
if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); }
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'); }
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
if (command.intelamt) {
if (!device.intelamt) { device.intelamt = {}; }
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { device.intelamt.ver = command.intelamt.ver; change = 1; changes.push('AMT version'); }
if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); }
if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); }
if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); }
if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); }
}
if (mesh.mtype == 2) {
if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); }
// 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.
}
// Get the node and change it if needed
obj.db.Get(obj.dbNodeKey, function (err, nodes) {
if (nodes.length != 1) return;
var device = nodes[0];
if (device.agent) {
var changes = [], change = 0;
// If there are changes, save and event
if (change == 1) {
obj.db.Set(device);
// Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
event.node = device;
obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
}
// Check if anything changes
if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); }
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'); }
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
if (command.intelamt) {
if (!device.intelamt) { device.intelamt = {}; }
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { device.intelamt.ver = command.intelamt.ver; change = 1; changes.push('AMT version'); }
if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); }
if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); }
if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); }
if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); }
}
});
if (mesh.mtype == 2) {
if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); }
// 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.
}
// If there are changes, save and event
if (change == 1) {
obj.db.Set(device);
// Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
event.node = device;
obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
}
}
});
}
// Change the current core information string and event it
function ChangeAgentLocationInfo(command) {
if ((command == null) || (command == null)) return; // Safety, should never happen.
if ((command == null) || (command == null)) { return; } // Safety, should never happen.
// Check that the mesh exists
obj.db.Get(obj.dbMeshKey, function (err, meshes) {
if (meshes.length != 1) return;
var mesh = meshes[0];
// Get the node and change it if needed
obj.db.Get(obj.dbNodeKey, function (err, nodes) {
if (nodes.length != 1) return;
var device = nodes[0];
if (device.agent) {
var changes = [], change = 0;
var mesh = obj.parent.meshes[obj.dbMeshKey];
if (mesh == null) return;
// Check if anything changes
if ((command.publicip) && (device.publicip != command.publicip)) { device.publicip = command.publicip; change = 1; changes.push('public ip'); }
if ((command.iploc) && (device.iploc != command.iploc)) { device.iploc = command.iploc; change = 1; changes.push('ip location'); }
// Get the node and change it if needed
obj.db.Get(obj.dbNodeKey, function (err, nodes) {
if (nodes.length != 1) { return; }
var device = nodes[0];
if (device.agent) {
var changes = [], change = 0;
// If there are changes, save and event
if (change == 1) {
obj.db.Set(device);
// Check if anything changes
if ((command.publicip) && (device.publicip != command.publicip)) { device.publicip = command.publicip; change = 1; changes.push('public ip'); }
if ((command.iploc) && (device.iploc != command.iploc)) { device.iploc = command.iploc; change = 1; changes.push('ip location'); }
// Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
event.node = device;
obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
}
// If there are changes, save and event
if (change == 1) {
obj.db.Set(device);
// Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) { delete device2.intelamt.pass; } // Remove the Intel AMT password before eventing this.
event.node = device;
obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event);
}
});
}
});
}

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.1.9-j",
"version": "0.1.9-k",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -1468,32 +1468,30 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
res.sendFile(argentInfo.path);
} else {
// We are going to embed the .msh file into the Windows executable (signed or not).
// First, query the meshid to build the .msh file
obj.db.Get('mesh/' + domain.id + '/' + req.query.meshid, function (err, meshes) {
if (meshes.length != 1) { res.sendStatus(401); return; }
var mesh = meshes[0];
// First, fetch the mesh object to build the .msh file
var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.meshid];
if (mesh == null) { res.sendStatus(401); return; }
// If required, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid];
var escUserId = obj.common.escapeFieldName(user._id);
if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
}
// If required, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid];
var escUserId = obj.common.escapeFieldName(user._id);
if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
}
var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
// Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
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 });
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 });
});
// Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
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 });
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 });
}
} else if (req.query.script != null) {
// Send a specific mesh install script back
@ -1602,32 +1600,30 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// If required, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true) && (req.session.userid == null)) { res.sendStatus(401); return; }
// Query the meshid
obj.db.Get('mesh/' + domain.id + '/' + req.query.id, function (err, meshes) {
if (meshes.length != 1) { res.sendStatus(401); return; }
var mesh = meshes[0];
// Fetch the mesh object
var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.id];
if (mesh == null) { res.sendStatus(401); return; }
// If needed, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid];
var escUserId = obj.common.escapeFieldName(user._id);
if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
}
// If needed, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid];
var escUserId = obj.common.escapeFieldName(user._id);
if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
}
var meshidhex = new Buffer(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var meshidhex = new Buffer(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
// Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
// Build the agent connection URL. If we are using a sub-domain or one with a DNS, we need to craft the URL correctly.
var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
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' });
res.send(meshsettings);
});
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' });
res.send(meshsettings);
}
// Add HTTP security headers to all responses