Added recovery core support.

This commit is contained in:
Ylian Saint-Hilaire 2019-01-21 14:05:50 -08:00
parent 34181f6400
commit 74a01ffb95
10 changed files with 504 additions and 132 deletions

283
agents/recoverycore.js Normal file
View File

@ -0,0 +1,283 @@
var http = require('http');
var childProcess = require('child_process');
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore Recovery", "caps": 10 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
var nextTunnelIndex = 1;
var tunnels = {};
function sendConsoleText(msg)
{
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg });
}
// Split a string taking into account the quoats. Used for command line parsing
function splitArgs(str)
{
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
return myArray;
}
// Parse arguments string array into an object
function parseArgs(argv)
{
var results = { '_': [] }, current = null;
for (var i = 1, len = argv.length; i < len; i++) {
var x = argv[i];
if (x.length > 2 && x[0] == '-' && x[1] == '-') {
if (current != null) { results[current] = true; }
current = x.substring(2);
} else {
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
}
}
if (current != null) { results[current] = true; }
return results;
}
// Get server target url with a custom path
function getServerTargetUrl(path)
{
var x = require('MeshAgent').ServerUrl;
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
if (x == null) { return null; }
if (path == null) { path = ''; }
x = http.parseUri(x);
if (x == null) return null;
return x.protocol + '//' + x.host + ':' + x.port + '/' + path;
}
// Get server url. If the url starts with "*/..." change it, it not use the url as is.
function getServerTargetUrlEx(url)
{
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
return url;
}
require('MeshAgent').on('Connected', function ()
{
require('os').name().then(function (v)
{
sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
require('MeshAgent').SendCommand(meshCoreObj);
});
});
// Tunnel callback operations
function onTunnelUpgrade(response, s, head) {
this.s = s;
s.httprequest = this;
s.end = onTunnelClosed;
s.tunnel = this;
//sendConsoleText('onTunnelUpgrade');
if (this.tcpport != null) {
// This is a TCP relay connection, pause now and try to connect to the target.
s.pause();
s.data = onTcpRelayServerTunnelData;
var connectionOptions = { port: parseInt(this.tcpport) };
if (this.tcpaddr != null) { connectionOptions.host = this.tcpaddr; } else { connectionOptions.host = '127.0.0.1'; }
s.tcprelay = net.createConnection(connectionOptions, onTcpRelayTargetTunnelConnect);
s.tcprelay.peerindex = this.index;
} else {
// This is a normal connect for KVM/Terminal/Files
s.data = onTunnelData;
}
}
require('MeshAgent').AddCommandHandler(function (data)
{
if (typeof data == 'object')
{
// If this is a console command, parse it and call the console handler
switch (data.action)
{
case 'msg':
{
switch (data.type)
{
case 'console': { // Process a console command
if (data.value && data.sessionid)
{
var args = splitArgs(data.value);
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
}
break;
}
case 'tunnel':
{
if (data.value != null) { // Process a new tunnel connection request
// Create a new tunnel object
var xurl = getServerTargetUrlEx(data.value);
if (xurl != null) {
var woptions = http.parseUri(xurl);
woptions.rejectUnauthorized = 0;
//sendConsoleText(JSON.stringify(woptions));
var tunnel = http.request(woptions);
tunnel.on('upgrade', function (response, s, head)
{
this.s = s;
s.httprequest = this;
s.tunnel = this;
s.on('end', function ()
{
if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
//sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
delete tunnels[this.httprequest.index];
// Clean up WebSocket
this.removeAllListeners('data');
});
s.on('data', function (data)
{
if (this.httprequest.state == 0) {
// Check if this is a relay connection
if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
} else {
// Handle tunnel data
if (this.httprequest.protocol == 0)
{
// Take a look at the protocol
this.httprequest.protocol = parseInt(data);
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
if (this.httprequest.protocol == 1)
{
// Remote terminal using native pipes
if (process.platform == "win32")
{
this.httprequest._term = require('win-terminal').Start(80, 25);
this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
}
else
{
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
this.httprequest.process.tunnel = this;
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
this.prependListener('end', function () { this.httprequest.process.kill(); });
}
this.on('end', function () {
if (process.platform == "win32")
{
// Unpipe the web socket
this.unpipe(this.httprequest._term);
this.httprequest._term.unpipe(this);
// Clean up
this.httprequest._term.end();
this.httprequest._term = null;
}
});
}
}
}
});
});
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
tunnel.sessionid = data.sessionid;
tunnel.rights = data.rights;
tunnel.state = 0;
tunnel.url = xurl;
tunnel.protocol = 0;
tunnel.tcpaddr = data.tcpaddr;
tunnel.tcpport = data.tcpport;
tunnel.end();
// Put the tunnel in the tunnels list
var index = nextTunnelIndex++;
tunnel.index = index;
tunnels[index] = tunnel;
//sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
}
}
break;
}
default:
// Unknown action, ignore it.
break;
}
break;
}
default:
// Unknown action, ignore it.
break;
}
}
});
function processConsoleCommand(cmd, args, rights, sessionid)
{
try
{
var response = null;
switch (cmd)
{
case 'help':
response = 'Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.';
break;
case 'osinfo': { // Return the operating system information
var i = 1;
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
for (var j = 0; j < i; j++) {
var pr = require('os').name();
pr.sessionid = sessionid;
pr.then(function (v) { sendConsoleText("OS: " + v, this.sessionid); });
}
break;
}
case 'dbkeys': { // Return all data store keys
response = JSON.stringify(db.Keys);
break;
}
case 'dbget': { // Return the data store value for a given key
if (db == null) { response = 'Database not accessible.'; break; }
if (args['_'].length != 1) {
response = 'Proper usage: dbget (key)'; // Display the value for a given database key
} else {
response = db.Get(args['_'][0]);
}
break;
}
case 'dbset': { // Set a data store key and value pair
if (db == null) { response = 'Database not accessible.'; break; }
if (args['_'].length != 2) {
response = 'Proper usage: dbset (key) (value)'; // Set a database key
} else {
var r = db.Put(args['_'][0], args['_'][1]);
response = 'Key set: ' + r;
}
break;
}
case 'dbcompact': { // Compact the data store
if (db == null) { response = 'Database not accessible.'; break; }
var r = db.Compact();
response = 'Database compacted: ' + r;
break;
}
case 'tunnels': { // Show the list of current tunnels
response = '';
for (var i in tunnels) { response += 'Tunnel #' + i + ', ' + tunnels[i].url + '\r\n'; }
if (response == '') { response = 'No websocket sessions.'; }
break;
}
case 'netinfo': { // Show network interface information
//response = objToString(mesh.NetInfo, 0, ' ');
var interfaces = require('os').networkInterfaces();
response = objToString(interfaces, 0, ' ', true);
break;
}
default: { // This is an unknown command, return an error message
response = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
break;
}
}
} catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); }
if (response != null) { sendConsoleText(response, sessionid); }
}

View File

@ -106,11 +106,12 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
const agentMeshCoreHash = (msg.length == 52) ? msg.substring(4, 52) : null; const agentMeshCoreHash = (msg.length == 52) ? msg.substring(4, 52) : null;
// We need to check if the core is current. First, figure out what core we need. // We need to check if the core is current. First, figure out what core we need.
const corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core; var corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core;
if (obj.agentCoreCheck == 1001) { corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].rcore; } // Use the recovery core.
if (corename != null) { if (corename != null) {
const meshcorehash = obj.parent.parent.defaultMeshCoresHash[corename]; const meshcorehash = obj.parent.parent.defaultMeshCoresHash[corename];
if (agentMeshCoreHash != meshcorehash) { if (agentMeshCoreHash != meshcorehash) {
if (obj.agentCoreCheck < 5) { if ((obj.agentCoreCheck < 5) || (obj.agentCoreCheck == 1001)) {
if (meshcorehash == null) { if (meshcorehash == null) {
// Clear the core // Clear the core
obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0)); // MeshCommand_CoreModule, ask mesh agent to clear the core obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0)); // MeshCommand_CoreModule, ask mesh agent to clear the core
@ -184,6 +185,11 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
obj.send(obj.agentUpdate.buf); // Command 14, mesh agent first data block obj.send(obj.agentUpdate.buf); // Command 14, mesh agent first data block
} }
}); });
} else {
// Check the mesh core, if the agent is capable of running one
if (((obj.agentInfo.capabilities & 16) != 0) && (obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core != null)) {
obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core hash.
}
} }
} }
} }
@ -398,51 +404,60 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Command 4, inform mesh agent that it's authenticated. // Command 4, inform mesh agent that it's authenticated.
obj.send(obj.common.ShortToStr(4)); 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 // Check if we need to make an native update check
obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId]; 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 const corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core;
if (corename == null) { obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0)); } // MeshCommand_CoreModule, ask mesh agent to clear the core
// Check if we already have IP location information for this node if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) {
obj.db.Get('iploc_' + obj.remoteaddr, function (err, iplocs) { // Ask the agent for it's executable binary hash
if (iplocs.length == 1) { obj.send(obj.common.ShortToStr(12) + obj.common.ShortToStr(0));
// We have a location in the database for this remote IP } else {
var iploc = nodes[0], x = {}; // Check the mesh core, if the agent is capable of running one
if ((iploc != null) && (iploc.ip != null) && (iploc.loc != null)) { if (((obj.agentInfo.capabilities & 16) != 0) && (corename != null)) { obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); } // Command 11, ask for mesh core hash.
x.publicip = iploc.ip; }
x.iploc = iploc.loc + ',' + (Math.floor((new Date(iploc.date)) / 1000));
ChangeAgentLocationInfo(x); // Do this if IP location is enabled on this domain TODO: Set IP location per device group?
} if (domain.iplocation == true) {
} else { // Check if we already have IP location information for this node
// Check if we need to ask for the IP location obj.db.Get('iploc_' + obj.remoteaddr, function (err, iplocs) {
var doIpLocation = 0; if (iplocs.length == 1) {
if (device.iploc == null) { // We have a location in the database for this remote IP
doIpLocation = 1; 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 { } else {
var loc = device.iploc.split(','); // Check if we need to ask for the IP location
if (loc.length < 3) { var doIpLocation = 0;
doIpLocation = 2; if (device.iploc == null) {
doIpLocation = 1;
} else { } else {
var t = new Date((parseFloat(loc[2]) * 1000)), now = Date.now(); var loc = device.iploc.split(',');
t.setDate(t.getDate() + 20); if (loc.length < 3) {
if (t < now) { doIpLocation = 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' }));
}
});
} }
} }
});
// 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' }));
}
});
}
}
});
}); });
} }

View File

@ -894,6 +894,16 @@ function CreateMeshCentralServer(config, args) {
'linux-noamt': 'var addedModules = [];\r\n' 'linux-noamt': 'var addedModules = [];\r\n'
}; };
// Read the recovery core if present
var meshRecoveryCore = null;
if (obj.fs.existsSync(obj.path.join(__dirname, 'agents', 'recoverycore.js')) == true) {
try { meshRecoveryCore = obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'recoverycore.js')).toString(); } catch (ex) { }
if (meshRecoveryCore != null) {
modulesAdd['windows-recovery'] = 'var addedModules = [];\r\n';
modulesAdd['linux-recovery'] = 'var addedModules = [];\r\n';
}
}
if (obj.args.minifycore !== false) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.min.js')).toString(); } catch (e) { } } // Favor minified meshcore if present. if (obj.args.minifycore !== false) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.min.js')).toString(); } catch (e) { } } // Favor minified meshcore if present.
if (meshCore == null) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.js')).toString(); } catch (e) { } } // Use non-minified meshcore. if (meshCore == null) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.js')).toString(); } catch (e) { } } // Use non-minified meshcore.
if (meshCore != null) { if (meshCore != null) {
@ -926,13 +936,24 @@ function CreateMeshCentralServer(config, args) {
modulesAdd['linux-amt'] += moduleData; modulesAdd['linux-amt'] += moduleData;
modulesAdd['linux-noamt'] += moduleData; modulesAdd['linux-noamt'] += moduleData;
} }
// Merge this module to recovery modules if needed
if (modulesAdd['windows-recovery'] != null) {
if ((moduleName == 'win-console') || (moduleName == 'win-message-pump') || (moduleName == 'win-terminal')) {
modulesAdd['windows-recovery'] += moduleData;
}
}
} }
} }
} }
// Merge the cores and compute the hashes // Merge the cores and compute the hashes
for (var i in modulesAdd) { for (var i in modulesAdd) {
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshCore; if ((i == 'windows-recovery') || (i == 'linux-recovery')) {
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshRecoveryCore;
} else {
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshCore;
}
obj.defaultMeshCoresHash[i] = obj.crypto.createHash('sha384').update(obj.defaultMeshCores[i]).digest("binary"); obj.defaultMeshCoresHash[i] = obj.crypto.createHash('sha384').update(obj.defaultMeshCores[i]).digest("binary");
obj.debug(1, 'Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes.'); obj.debug(1, 'Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes.');
//console.log('Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes.'); // DEBUG, Print the core size //console.log('Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes.'); // DEBUG, Print the core size
@ -1027,34 +1048,34 @@ function CreateMeshCentralServer(config, args) {
// List of possible mesh agents // List of possible mesh agents
obj.meshAgentsArchitectureNumbers = { obj.meshAgentsArchitectureNumbers = {
0: { id: 0, localname: 'Unknown', rname: 'meshconsole.exe', desc: 'Unknown agent', update: false, amt: true, platform: 'unknown', core: 'linux-noamt' }, 0: { id: 0, localname: 'Unknown', rname: 'meshconsole.exe', desc: 'Unknown agent', update: false, amt: true, platform: 'unknown', core: 'linux-noamt', rcore: 'linux-recovery' },
1: { id: 1, localname: 'MeshConsole.exe', rname: 'meshconsole.exe', desc: 'Windows x86-32 console', update: true, amt: true, platform: 'win32', core: 'windows-amt' }, 1: { id: 1, localname: 'MeshConsole.exe', rname: 'meshconsole.exe', desc: 'Windows x86-32 console', update: true, amt: true, platform: 'win32', core: 'windows-amt', rcore: 'windows-recovery' },
2: { id: 2, localname: 'MeshConsole64.exe', rname: 'meshconsole.exe', desc: 'Windows x86-64 console', update: true, amt: true, platform: 'win32', core: 'windows-amt' }, 2: { id: 2, localname: 'MeshConsole64.exe', rname: 'meshconsole.exe', desc: 'Windows x86-64 console', update: true, amt: true, platform: 'win32', core: 'windows-amt', rcore: 'windows-recovery' },
3: { id: 3, localname: 'MeshService-signed.exe', rname: 'meshagent.exe', desc: 'Windows x86-32 service', update: true, amt: true, platform: 'win32', core: 'windows-amt' }, 3: { id: 3, localname: 'MeshService-signed.exe', rname: 'meshagent.exe', desc: 'Windows x86-32 service', update: true, amt: true, platform: 'win32', core: 'windows-amt', rcore: 'windows-recovery' },
4: { id: 4, localname: 'MeshService64-signed.exe', rname: 'meshagent.exe', desc: 'Windows x86-64 service', update: true, amt: true, platform: 'win32', core: 'windows-amt' }, 4: { id: 4, localname: 'MeshService64-signed.exe', rname: 'meshagent.exe', desc: 'Windows x86-64 service', update: true, amt: true, platform: 'win32', core: 'windows-amt', rcore: 'windows-recovery' },
5: { id: 5, localname: 'meshagent_x86', rname: 'meshagent', desc: 'Linux x86-32', update: true, amt: true, platform: 'linux', core: 'linux-amt' }, 5: { id: 5, localname: 'meshagent_x86', rname: 'meshagent', desc: 'Linux x86-32', update: true, amt: true, platform: 'linux', core: 'linux-amt', rcore: 'linux-recovery' },
6: { id: 6, localname: 'meshagent_x86-64', rname: 'meshagent', desc: 'Linux x86-64', update: true, amt: true, platform: 'linux', core: 'linux-amt' }, 6: { id: 6, localname: 'meshagent_x86-64', rname: 'meshagent', desc: 'Linux x86-64', update: true, amt: true, platform: 'linux', core: 'linux-amt', rcore: 'linux-recovery' },
7: { id: 7, localname: 'meshagent_mips', rname: 'meshagent', desc: 'Linux MIPS', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 7: { id: 7, localname: 'meshagent_mips', rname: 'meshagent', desc: 'Linux MIPS', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
8: { id: 8, localname: 'MeshAgent-Linux-XEN-x86-32', rname: 'meshagent', desc: 'XEN x86-64', update: true, amt: false, platform: 'linux', core: 'linux-amt' }, 8: { id: 8, localname: 'MeshAgent-Linux-XEN-x86-32', rname: 'meshagent', desc: 'XEN x86-64', update: true, amt: false, platform: 'linux', core: 'linux-amt', rcore: 'linux-recovery' },
9: { id: 9, localname: 'meshagent_arm', rname: 'meshagent', desc: 'Linux ARM5', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 9: { id: 9, localname: 'meshagent_arm', rname: 'meshagent', desc: 'Linux ARM5', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
10: { id: 10, localname: 'MeshAgent-Linux-ARM-PlugPC', rname: 'meshagent', desc: 'Linux ARM PlugPC', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 10: { id: 10, localname: 'MeshAgent-Linux-ARM-PlugPC', rname: 'meshagent', desc: 'Linux ARM PlugPC', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
11: { id: 11, localname: 'meshagent_osx-x86-32', rname: 'meshosx', desc: 'Apple OSX x86-32', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 11: { id: 11, localname: 'meshagent_osx-x86-32', rname: 'meshosx', desc: 'Apple OSX x86-32', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
12: { id: 12, localname: 'MeshAgent-Android-x86', rname: 'meshandroid', desc: 'Android x86-32', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 12: { id: 12, localname: 'MeshAgent-Android-x86', rname: 'meshandroid', desc: 'Android x86-32', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
13: { id: 13, localname: 'meshagent_pogo', rname: 'meshagent', desc: 'Linux ARM PogoPlug', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 13: { id: 13, localname: 'meshagent_pogo', rname: 'meshagent', desc: 'Linux ARM PogoPlug', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
14: { id: 14, localname: 'MeshAgent-Android-APK', rname: 'meshandroid', desc: 'Android Market', update: false, amt: false, platform: 'android', core: 'linux-noamt' }, // Get this one from Google Play 14: { id: 14, localname: 'MeshAgent-Android-APK', rname: 'meshandroid', desc: 'Android Market', update: false, amt: false, platform: 'android', core: 'linux-noamt', rcore: 'linux-recovery' }, // Get this one from Google Play
15: { id: 15, localname: 'meshagent_poky', rname: 'meshagent', desc: 'Linux Poky x86-32', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 15: { id: 15, localname: 'meshagent_poky', rname: 'meshagent', desc: 'Linux Poky x86-32', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
16: { id: 16, localname: 'meshagent_osx-x86-64', rname: 'meshagent', desc: 'Apple OSX x86-64', update: true, amt: false, platform: 'osx', core: 'linux-noamt' }, 16: { id: 16, localname: 'meshagent_osx-x86-64', rname: 'meshagent', desc: 'Apple OSX x86-64', update: true, amt: false, platform: 'osx', core: 'linux-noamt', rcore: 'linux-recovery' },
17: { id: 17, localname: 'MeshAgent-ChromeOS', rname: 'meshagent', desc: 'Google ChromeOS', update: false, amt: false, platform: 'chromeos', core: 'linux-noamt' }, // Get this one from Chrome store 17: { id: 17, localname: 'MeshAgent-ChromeOS', rname: 'meshagent', desc: 'Google ChromeOS', update: false, amt: false, platform: 'chromeos', core: 'linux-noamt', rcore: 'linux-recovery' }, // Get this one from Chrome store
18: { id: 18, localname: 'meshagent_poky64', rname: 'meshagent', desc: 'Linux Poky x86-64', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 18: { id: 18, localname: 'meshagent_poky64', rname: 'meshagent', desc: 'Linux Poky x86-64', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
19: { id: 19, localname: 'meshagent_x86_nokvm', rname: 'meshagent', desc: 'Linux x86-32 NoKVM', update: true, amt: true, platform: 'linux', core: 'linux-amt' }, 19: { id: 19, localname: 'meshagent_x86_nokvm', rname: 'meshagent', desc: 'Linux x86-32 NoKVM', update: true, amt: true, platform: 'linux', core: 'linux-amt', rcore: 'linux-recovery' },
20: { id: 20, localname: 'meshagent_x86-64_nokvm', rname: 'meshagent', desc: 'Linux x86-64 NoKVM', update: true, amt: true, platform: 'linux', core: 'linux-amt' }, 20: { id: 20, localname: 'meshagent_x86-64_nokvm', rname: 'meshagent', desc: 'Linux x86-64 NoKVM', update: true, amt: true, platform: 'linux', core: 'linux-amt', rcore: 'linux-recovery' },
21: { id: 21, localname: 'MeshAgent-WinMinCore-Console-x86-32.exe', rname: 'meshagent.exe', desc: 'Windows MinCore Console x86-32', update: true, amt: false, platform: 'win32', core: 'windows-amt' }, 21: { id: 21, localname: 'MeshAgent-WinMinCore-Console-x86-32.exe', rname: 'meshagent.exe', desc: 'Windows MinCore Console x86-32', update: true, amt: false, platform: 'win32', core: 'windows-amt', rcore: 'windows-recovery' },
22: { id: 22, localname: 'MeshAgent-WinMinCore-Service-x86-64.exe', rname: 'meshagent.exe', desc: 'Windows MinCore Service x86-32', update: true, amt: false, platform: 'win32', core: 'windows-amt' }, 22: { id: 22, localname: 'MeshAgent-WinMinCore-Service-x86-64.exe', rname: 'meshagent.exe', desc: 'Windows MinCore Service x86-32', update: true, amt: false, platform: 'win32', core: 'windows-amt', rcore: 'windows-recovery' },
23: { id: 23, localname: 'MeshAgent-NodeJS', rname: 'meshagent', desc: 'NodeJS', update: false, amt: false, platform: 'node', core: 'linux-noamt' }, // Get this one from NPM 23: { id: 23, localname: 'MeshAgent-NodeJS', rname: 'meshagent', desc: 'NodeJS', update: false, amt: false, platform: 'node', core: 'linux-noamt', rcore: 'linux-recovery' }, // Get this one from NPM
24: { id: 24, localname: 'meshagent_arm-linaro', rname: 'meshagent', desc: 'Linux ARM Linaro', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, 24: { id: 24, localname: 'meshagent_arm-linaro', rname: 'meshagent', desc: 'Linux ARM Linaro', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' },
25: { id: 25, localname: 'meshagent_armhf', rname: 'meshagent', desc: 'Linux ARM - HardFloat', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, // "armv6l" and "armv7l" 25: { id: 25, localname: 'meshagent_armhf', rname: 'meshagent', desc: 'Linux ARM - HardFloat', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery' }, // "armv6l" and "armv7l"
10003: { id: 3, localname: 'MeshService.exe', rname: 'meshagent.exe', desc: 'Windows x86-32 service', update: true, amt: true, platform: 'win32', core: 'windows-amt' }, // Unsigned version of the Windows MeshAgent x86 10003: { id: 3, localname: 'MeshService.exe', rname: 'meshagent.exe', desc: 'Windows x86-32 service', update: true, amt: true, platform: 'win32', core: 'windows-amt', rcore: 'linux-recovery' }, // Unsigned version of the Windows MeshAgent x86
10004: { id: 4, localname: 'MeshService64.exe', rname: 'meshagent.exe', desc: 'Windows x86-64 service', update: true, amt: true, platform: 'win32', core: 'windows-amt' } // Unsigned version of the Windows MeshAgent x64 10004: { id: 4, localname: 'MeshService64.exe', rname: 'meshagent.exe', desc: 'Windows x86-64 service', update: true, amt: true, platform: 'win32', core: 'windows-amt', rcore: 'linux-recovery' } // Unsigned version of the Windows MeshAgent x64
}; };
// Update the list of available mesh agents // Update the list of available mesh agents

View File

@ -1215,27 +1215,27 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
{ {
if (user.siteadmin != 0xFFFFFFFF) break; if (user.siteadmin != 0xFFFFFFFF) break;
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
if (command.path) { if (obj.common.validateString(command.type, 1, 40) == false) break; // Check path
if (obj.common.validateString(command.path, 1, 4096) == false) break; // Check path if (command.type == 'default') {
if (command.path == '*') { // Send the default core to the agent
// Update the server default core and send a core hash request obj.parent.parent.updateMeshCore(function () { obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'default'); });
// Load default mesh agent core if present, then perform a core update } else if (command.type == 'clear') {
obj.parent.parent.updateMeshCore(function () { obj.parent.sendMeshAgentCore(user, domain, command.nodeid, '*'); });
} else {
// Send a mesh agent core to the mesh agent
var file = obj.parent.getServerFilePath(user, domain, command.path);
if (file != null) {
obj.parent.parent.fs.readFile(file.fullpath, 'utf8', function (err, data) {
if (err != null) {
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, data);
}
});
}
}
} else {
// Clear the mesh agent core on the mesh agent // Clear the mesh agent core on the mesh agent
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, null); obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'clear');
} else if (command.type == 'recovery') {
// Send the recovery core to the agent
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'recovery');
} else if ((command.type == 'custom') && (obj.common.validateString(command.path, 1, 2048) == true)) {
// Send a mesh agent core to the mesh agent
var file = obj.parent.getServerFilePath(user, domain, command.path);
if (file != null) {
obj.parent.parent.fs.readFile(file.fullpath, 'utf8', function (err, data) {
if (err != null) {
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'custom', data);
}
});
}
} }
break; break;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.2.6-n", "version": "0.2.6-o",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1417,6 +1417,7 @@
var deviceHeaders = {}; var deviceHeaders = {};
var deviceHeadersTitles = {}; var deviceHeadersTitles = {};
function updateDevicesEx() { function updateDevicesEx() {
if (updateDevicesTimer != null) { clearTimeout(updateDevicesTimer); updateDevicesTimer = null; }
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {}; var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
// 3 wide, list view or desktop view // 3 wide, list view or desktop view

View File

@ -939,7 +939,7 @@
Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
// Display the page devices // Display the page devices
onSortSelectChange(); onSortSelectChange(true);
onSearchInputChanged(); onSearchInputChanged();
for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); } for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel'); Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
@ -1106,6 +1106,34 @@
if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); } if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); }
} }
// When the list of events needs to be updated, put a small delay so that the browser
// performs much less work when event storms happen.
var updateEventsNaggleTimer = null;
function updateEventsNaggle() {
if (updateEventsNaggleTimer == null) {
updateEventsNaggleTimer = setTimeout(function () {
events_update();
updateEventsNaggleTimer = null;
}, 100);
}
}
// When the list of devices needs to be updated, put a small delay so that the browser
// performs much less work when event storms happen.
var updateDevicesNaggleTimer = null;
function updateDevicesNaggle() {
if (updateDevicesNaggleTimer == null) {
updateDevicesNaggleTimer = setTimeout(function () {
onSortSelectChange(true);
drawNotifications();
onSearchInputChanged();
updateDevices();
updateMapMarkers();
updateDevicesNaggleTimer = null;
}, 100);
}
}
function onMessage(server, message) { function onMessage(server, message) {
switch (message.action) { switch (message.action) {
case 'serverstats': { case 'serverstats': {
@ -1166,9 +1194,10 @@
nodes.push(message.nodes[m][n]); nodes.push(message.nodes[m][n]);
} }
} }
onSortSelectChange(); //onSortSelectChange(true);
onSearchInputChanged(); //onSearchInputChanged();
updateDevices(); //updateDevices();
updateDevicesNaggle();
refreshMap(false, true); refreshMap(false, true);
if (xxcurrentView == 0) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } } if (xxcurrentView == 0) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } }
if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));} if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));}
@ -1284,7 +1313,8 @@
userEvents_update(); userEvents_update();
} else { } else {
events = message.events; events = message.events;
events_update(); updateEventsNaggle();
//events_update();
} }
break; break;
} }
@ -1339,7 +1369,8 @@
events.unshift(message.event); events.unshift(message.event);
var eventLimit = parseInt(p3limitdropdown.value); var eventLimit = parseInt(p3limitdropdown.value);
while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
events_update(); updateEventsNaggle();
//events_update();
} }
switch (message.event.action) { switch (message.event.action) {
case 'accountcreate': case 'accountcreate':
@ -1442,10 +1473,14 @@
if (!node.icon) node.icon = 1; if (!node.icon) node.icon = 1;
node.ident = ++nodeShortIdent; node.ident = ++nodeShortIdent;
nodes.push(node); nodes.push(node);
onSortSelectChange();
onSearchInputChanged(); // Web page update
updateDevices(); updateDevicesNaggle();
updateMapMarkers(); //onSortSelectChange(true);
//onSearchInputChanged();
//updateDevices();
//updateMapMarkers();
break; break;
} }
case 'removenode': { case 'removenode': {
@ -1459,8 +1494,11 @@
// TODO: Correctly disconnect from this node (Desktop/Terminal/Files...) // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
} }
nodes.splice(index, 1); nodes.splice(index, 1);
updateDevices();
updateMapMarkers(); // Web page update
updateDevicesNaggle();
//updateDevices();
//updateMapMarkers();
} }
break; break;
} }
@ -1503,10 +1541,13 @@
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; } if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
if (message.event.node.icon) { node.icon = message.event.node.icon; } if (message.event.node.icon) { node.icon = message.event.node.icon; }
onSortSelectChange(true); // Web page update
drawNotifications(); updateDevicesNaggle();
//onSortSelectChange(true);
//drawNotifications();
//updateMapMarkers();
refreshDevice(node._id); refreshDevice(node._id);
updateMapMarkers();
if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); } if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
} }
@ -1522,8 +1563,12 @@
// Change the node connection state // Change the node connection state
node.conn = message.event.conn; node.conn = message.event.conn;
node.pwr = message.event.pwr; node.pwr = message.event.pwr;
updateDevices();
updateMapMarkers(); // Web page update
updateDevicesNaggle();
//updateDevices();
//updateMapMarkers();
refreshDevice(node._id); refreshDevice(node._id);
} }
break; break;
@ -1542,7 +1587,8 @@
} }
case 'clearevents': { case 'clearevents': {
events = []; events = [];
events_update(); updateEventsNaggle();
//events_update();
break; break;
} }
case 'login': { case 'login': {
@ -1601,7 +1647,7 @@
function onRealNameCheckBox() { function onRealNameCheckBox() {
showRealNames = Q('RealNameCheckBox').checked; showRealNames = Q('RealNameCheckBox').checked;
putstore("showRealNames", showRealNames ? 1 : 0); putstore("showRealNames", showRealNames ? 1 : 0);
onSortSelectChange(); onSortSelectChange(true);
return; return;
} }
@ -1635,7 +1681,7 @@
showRealNames = !showRealNames; showRealNames = !showRealNames;
Q('RealNameCheckBox').value = showRealNames; Q('RealNameCheckBox').value = showRealNames;
putstore("showRealNames", showRealNames ? 1 : 0); putstore("showRealNames", showRealNames ? 1 : 0);
onSortSelectChange(); onSortSelectChange(true);
return; return;
} }
if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return; if (e.ctrlKey == true || e.altKey == true || e.metaKey == true) return;
@ -5008,16 +5054,16 @@
if (e.shiftKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, path:'*' }); } // Upload default core if (e.shiftKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, path:'*' }); } // Upload default core
else if (e.altKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id }); } // Clear the core else if (e.altKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id }); } // Clear the core
else if (e.ctrlKey == true) { p15uploadCore2(); } // Upload the core from a file else if (e.ctrlKey == true) { p15uploadCore2(); } // Upload the core from a file
else { setDialogMode(2, "Change Mesh Agent Core", 3, p15uploadCoreEx, '<select id=d3coreMode style=float:right;width:260px><option value=1>Upload default server core</option><option value=2>Clear the core</option><option value=3>Upload a core file</option><option value=4>Soft disconnect agent</option><option value=5>Hard disconnect agent</option></select><div>Change Core</div>'); } else { setDialogMode(2, "Change Mesh Agent Core", 3, p15uploadCoreEx, '<select id=d3coreMode style=float:right;width:260px><option value=1>Upload default server core</option><option value=2>Clear the core</option><option value=6>Upload recovery core</option><option value=3>Upload a core file</option><option value=4>Soft disconnect agent</option><option value=5>Hard disconnect agent</option></select><div>Change Core</div>'); }
} }
function p15uploadCoreEx() { function p15uploadCoreEx() {
if (Q('d3coreMode').value == 1) { if (Q('d3coreMode').value == 1) {
// Upload default core // Upload default core
meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, path:'*' }); meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'default' });
} else if (Q('d3coreMode').value == 2) { } else if (Q('d3coreMode').value == 2) {
// Clear the core // Clear the core
meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id }); meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'clear' });
} else if (Q('d3coreMode').value == 3) { } else if (Q('d3coreMode').value == 3) {
// Upload file as core // Upload file as core
p15uploadCore2(); p15uploadCore2();
@ -5027,6 +5073,9 @@
} else if (Q('d3coreMode').value == 5) { } else if (Q('d3coreMode').value == 5) {
// Hard disconnect the mesh agent // Hard disconnect the mesh agent
meshserver.send({ action: 'agentdisconnect', nodeid: consoleNode._id, disconnectMode: 2 }); meshserver.send({ action: 'agentdisconnect', nodeid: consoleNode._id, disconnectMode: 2 });
} else if (Q('d3coreMode').value == 6) {
// Upload a recovery core
meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type:'recovery' });
} }
} }
@ -5047,7 +5096,7 @@
} else { } else {
// Upload server mesh agent code // Upload server mesh agent code
var files = d3getFileSel(); var files = d3getFileSel();
if (files.length == 1) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, path: d3filetreelocation.join('/') + '/' + files[0] }); } if (files.length == 1) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'custom', path: d3filetreelocation.join('/') + '/' + files[0] }); }
} }
} }

View File

@ -754,7 +754,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
res.sendStatus(404); return; res.sendStatus(404); return;
} else { } else {
nologout = true; nologout = true;
req.session.userid = 'user/' + domain.id + '/' + req.connection.user; req.session.userid = 'user/' + domain.id + '/' + req.connection.user.toLowerCase();
req.session.usersid = req.connection.userSid; req.session.usersid = req.connection.userSid;
req.session.usersGroups = req.connection.userGroups; req.session.usersGroups = req.connection.userGroups;
req.session.domainid = domain.id; req.session.domainid = domain.id;
@ -1108,7 +1108,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
obj.fs.readFile(file.path, 'utf8', function (err, data) { obj.fs.readFile(file.path, 'utf8', function (err, data) {
if (err != null) return; if (err != null) return;
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw) data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
obj.sendMeshAgentCore(user, domain, fields.attrib[0], data); // Upload the core obj.sendMeshAgentCore(user, domain, fields.attrib[0], 'custom', data); // Upload the core
try { obj.fs.unlinkSync(file.path); } catch (e) { } try { obj.fs.unlinkSync(file.path); } catch (e) { }
}); });
} }
@ -2105,31 +2105,34 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
}; };
// Send the core module to the mesh agent // Send the core module to the mesh agent
obj.sendMeshAgentCore = function (user, domain, nodeid, core) { obj.sendMeshAgentCore = function (user, domain, nodeid, coretype, coredata) {
if (nodeid == null) return; if (nodeid == null) return;
var splitnode = nodeid.split('/'); const splitnode = nodeid.split('/');
if ((splitnode.length != 3) || (splitnode[1] != domain.id)) return; // Check that nodeid is valid and part of our domain if ((splitnode.length != 3) || (splitnode[1] != domain.id)) return; // Check that nodeid is valid and part of our domain
var agent = obj.wsagents[nodeid];
// TODO: This command only works if the agent is connected on the same server. Will not work with multi server peering.
const agent = obj.wsagents[nodeid];
if (agent == null) return; if (agent == null) return;
// Check we have agent rights // Check we have agent rights
var rights = user.links[agent.dbMeshKey].rights; var rights = user.links[agent.dbMeshKey].rights;
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) { if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) {
if (core == null) { if (coretype == 'clear') {
// Clear the mesh agent core // Clear the mesh agent core
agent.agentCoreCheck = 1000; // Tell the agent object we are not using a custom core. agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom core.
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0)); agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0));
} else if (core == '*') { } else if (coretype == 'default') {
// Reset to default code
agent.agentCoreCheck = 0; // Tell the agent object we are using a default code agent.agentCoreCheck = 0; // Tell the agent object we are using a default code
// Reset the core to the server default
agent.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core hash. agent.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core hash.
} else { } else if (coretype == 'recovery') {
agent.agentCoreCheck = 1000; // Tell the agent object we are not using a custom core. // Reset to recovery core
// Perform a SHA384 hash on the core module agent.agentCoreCheck = 1001; // Tell the agent object we are using the recovery core.
var hash = obj.crypto.createHash('sha384').update(Buffer.from(core, 'binary')).digest().toString('binary'); agent.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core hash.
} else if (coretype == 'custom') {
// Send the code module to the agent agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom core.
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + hash + core); const hash = obj.crypto.createHash('sha384').update(Buffer.from(core, 'binary')).digest().toString('binary'); // Perform a SHA384 hash on the core module
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + hash + core); // Send the code module to the agent
} }
} }
}; };