mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
Added recovery core support.
This commit is contained in:
parent
34181f6400
commit
74a01ffb95
283
agents/recoverycore.js
Normal file
283
agents/recoverycore.js
Normal 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); }
|
||||
}
|
95
meshagent.js
95
meshagent.js
@ -106,11 +106,12 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
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.
|
||||
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) {
|
||||
const meshcorehash = obj.parent.parent.defaultMeshCoresHash[corename];
|
||||
if (agentMeshCoreHash != meshcorehash) {
|
||||
if (obj.agentCoreCheck < 5) {
|
||||
if ((obj.agentCoreCheck < 5) || (obj.agentCoreCheck == 1001)) {
|
||||
if (meshcorehash == null) {
|
||||
// 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
|
||||
}
|
||||
});
|
||||
} 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.
|
||||
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
|
||||
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
|
||||
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 {
|
||||
// Check if we need to ask for the IP location
|
||||
var doIpLocation = 0;
|
||||
if (device.iploc == null) {
|
||||
doIpLocation = 1;
|
||||
if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) {
|
||||
// Ask the agent for it's executable binary hash
|
||||
obj.send(obj.common.ShortToStr(12) + obj.common.ShortToStr(0));
|
||||
} else {
|
||||
// Check the mesh core, if the agent is capable of running one
|
||||
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.
|
||||
}
|
||||
|
||||
// Do this if IP location is enabled on this domain TODO: Set IP location per device group?
|
||||
if (domain.iplocation == true) {
|
||||
// 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 {
|
||||
var loc = device.iploc.split(',');
|
||||
if (loc.length < 3) {
|
||||
doIpLocation = 2;
|
||||
// Check if we need to ask for the IP location
|
||||
var doIpLocation = 0;
|
||||
if (device.iploc == null) {
|
||||
doIpLocation = 1;
|
||||
} else {
|
||||
var t = new Date((parseFloat(loc[2]) * 1000)), now = Date.now();
|
||||
t.setDate(t.getDate() + 20);
|
||||
if (t < now) { doIpLocation = 3; }
|
||||
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' }));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 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' }));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -894,6 +894,16 @@ function CreateMeshCentralServer(config, args) {
|
||||
'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 (meshCore == null) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.js')).toString(); } catch (e) { } } // Use non-minified meshcore.
|
||||
if (meshCore != null) {
|
||||
@ -926,13 +936,24 @@ function CreateMeshCentralServer(config, args) {
|
||||
modulesAdd['linux-amt'] += 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
|
||||
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.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
|
||||
@ -1027,34 +1048,34 @@ function CreateMeshCentralServer(config, args) {
|
||||
|
||||
// List of possible mesh agents
|
||||
obj.meshAgentsArchitectureNumbers = {
|
||||
0: { id: 0, localname: 'Unknown', rname: 'meshconsole.exe', desc: 'Unknown agent', update: false, amt: true, platform: 'unknown', core: 'linux-noamt' },
|
||||
1: { id: 1, localname: 'MeshConsole.exe', rname: 'meshconsole.exe', desc: 'Windows x86-32 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' },
|
||||
3: { id: 3, localname: 'MeshService-signed.exe', rname: 'meshagent.exe', desc: 'Windows x86-32 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' },
|
||||
5: { id: 5, localname: 'meshagent_x86', rname: 'meshagent', desc: 'Linux x86-32', 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' },
|
||||
7: { id: 7, localname: 'meshagent_mips', rname: 'meshagent', desc: 'Linux MIPS', update: true, amt: false, platform: 'linux', core: 'linux-noamt' },
|
||||
8: { id: 8, localname: 'MeshAgent-Linux-XEN-x86-32', rname: 'meshagent', desc: 'XEN x86-64', update: true, amt: false, platform: 'linux', core: 'linux-amt' },
|
||||
9: { id: 9, localname: 'meshagent_arm', rname: 'meshagent', desc: 'Linux ARM5', 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' },
|
||||
11: { id: 11, localname: 'meshagent_osx-x86-32', rname: 'meshosx', desc: 'Apple OSX 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' },
|
||||
13: { id: 13, localname: 'meshagent_pogo', rname: 'meshagent', desc: 'Linux ARM PogoPlug', update: true, amt: false, platform: 'linux', core: 'linux-noamt' },
|
||||
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
|
||||
15: { id: 15, localname: 'meshagent_poky', rname: 'meshagent', desc: 'Linux Poky x86-32', update: true, amt: false, platform: 'linux', 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' },
|
||||
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
|
||||
18: { id: 18, localname: 'meshagent_poky64', rname: 'meshagent', desc: 'Linux Poky x86-64', update: true, amt: false, platform: 'linux', core: 'linux-noamt' },
|
||||
19: { id: 19, localname: 'meshagent_x86_nokvm', rname: 'meshagent', desc: 'Linux x86-32 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' },
|
||||
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' },
|
||||
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' },
|
||||
23: { id: 23, localname: 'MeshAgent-NodeJS', rname: 'meshagent', desc: 'NodeJS', update: false, amt: false, platform: 'node', core: 'linux-noamt' }, // 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' },
|
||||
25: { id: 25, localname: 'meshagent_armhf', rname: 'meshagent', desc: 'Linux ARM - HardFloat', update: true, amt: false, platform: 'linux', core: 'linux-noamt' }, // "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
|
||||
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
|
||||
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', 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', 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', 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', rcore: 'windows-recovery' },
|
||||
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', rcore: 'linux-recovery' },
|
||||
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', rcore: 'linux-recovery' },
|
||||
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', 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', 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', rcore: 'linux-recovery' },
|
||||
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', 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', 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', rcore: 'linux-recovery' },
|
||||
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', 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', 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', 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', 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', rcore: 'windows-recovery' },
|
||||
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', rcore: 'linux-recovery' },
|
||||
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', 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', rcore: 'linux-recovery' } // Unsigned version of the Windows MeshAgent x64
|
||||
};
|
||||
|
||||
// Update the list of available mesh agents
|
||||
|
40
meshuser.js
40
meshuser.js
@ -1215,27 +1215,27 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
{
|
||||
if (user.siteadmin != 0xFFFFFFFF) break;
|
||||
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if (command.path) {
|
||||
if (obj.common.validateString(command.path, 1, 4096) == false) break; // Check path
|
||||
if (command.path == '*') {
|
||||
// Update the server default core and send a core hash request
|
||||
// Load default mesh agent core if present, then perform a core update
|
||||
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 {
|
||||
if (obj.common.validateString(command.type, 1, 40) == false) break; // Check path
|
||||
if (command.type == 'default') {
|
||||
// Send the default core to the agent
|
||||
obj.parent.parent.updateMeshCore(function () { obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'default'); });
|
||||
} else if (command.type == 'clear') {
|
||||
// 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;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.2.6-n",
|
||||
"version": "0.2.6-o",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1417,6 +1417,7 @@
|
||||
var deviceHeaders = {};
|
||||
var deviceHeadersTitles = {};
|
||||
function updateDevicesEx() {
|
||||
if (updateDevicesTimer != null) { clearTimeout(updateDevicesTimer); updateDevicesTimer = null; }
|
||||
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
|
||||
|
||||
// 3 wide, list view or desktop view
|
||||
|
@ -939,7 +939,7 @@
|
||||
Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
|
||||
|
||||
// Display the page devices
|
||||
onSortSelectChange();
|
||||
onSortSelectChange(true);
|
||||
onSearchInputChanged();
|
||||
for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
|
||||
Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
|
||||
@ -1106,6 +1106,34 @@
|
||||
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) {
|
||||
switch (message.action) {
|
||||
case 'serverstats': {
|
||||
@ -1166,9 +1194,10 @@
|
||||
nodes.push(message.nodes[m][n]);
|
||||
}
|
||||
}
|
||||
onSortSelectChange();
|
||||
onSearchInputChanged();
|
||||
updateDevices();
|
||||
//onSortSelectChange(true);
|
||||
//onSearchInputChanged();
|
||||
//updateDevices();
|
||||
updateDevicesNaggle();
|
||||
refreshMap(false, true);
|
||||
if (xxcurrentView == 0) { if ('{{viewmode}}' != '') { go(parseInt('{{viewmode}}')); } else { setDialogMode(0); go(1); } }
|
||||
if ('{{currentNode}}' != '') { gotoDevice('{{currentNode}}',parseInt('{{viewmode}}'));}
|
||||
@ -1284,7 +1313,8 @@
|
||||
userEvents_update();
|
||||
} else {
|
||||
events = message.events;
|
||||
events_update();
|
||||
updateEventsNaggle();
|
||||
//events_update();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1339,7 +1369,8 @@
|
||||
events.unshift(message.event);
|
||||
var eventLimit = parseInt(p3limitdropdown.value);
|
||||
while (events.length > eventLimit) { events.pop(); } // Remove element(s) at the end
|
||||
events_update();
|
||||
updateEventsNaggle();
|
||||
//events_update();
|
||||
}
|
||||
switch (message.event.action) {
|
||||
case 'accountcreate':
|
||||
@ -1442,10 +1473,14 @@
|
||||
if (!node.icon) node.icon = 1;
|
||||
node.ident = ++nodeShortIdent;
|
||||
nodes.push(node);
|
||||
onSortSelectChange();
|
||||
onSearchInputChanged();
|
||||
updateDevices();
|
||||
updateMapMarkers();
|
||||
|
||||
// Web page update
|
||||
updateDevicesNaggle();
|
||||
//onSortSelectChange(true);
|
||||
//onSearchInputChanged();
|
||||
//updateDevices();
|
||||
//updateMapMarkers();
|
||||
|
||||
break;
|
||||
}
|
||||
case 'removenode': {
|
||||
@ -1459,8 +1494,11 @@
|
||||
// TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
|
||||
}
|
||||
nodes.splice(index, 1);
|
||||
updateDevices();
|
||||
updateMapMarkers();
|
||||
|
||||
// Web page update
|
||||
updateDevicesNaggle();
|
||||
//updateDevices();
|
||||
//updateMapMarkers();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1503,10 +1541,13 @@
|
||||
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
|
||||
if (message.event.node.icon) { node.icon = message.event.node.icon; }
|
||||
|
||||
onSortSelectChange(true);
|
||||
drawNotifications();
|
||||
// Web page update
|
||||
updateDevicesNaggle();
|
||||
//onSortSelectChange(true);
|
||||
//drawNotifications();
|
||||
//updateMapMarkers();
|
||||
|
||||
refreshDevice(node._id);
|
||||
updateMapMarkers();
|
||||
|
||||
if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
|
||||
}
|
||||
@ -1522,8 +1563,12 @@
|
||||
// Change the node connection state
|
||||
node.conn = message.event.conn;
|
||||
node.pwr = message.event.pwr;
|
||||
updateDevices();
|
||||
updateMapMarkers();
|
||||
|
||||
// Web page update
|
||||
updateDevicesNaggle();
|
||||
//updateDevices();
|
||||
//updateMapMarkers();
|
||||
|
||||
refreshDevice(node._id);
|
||||
}
|
||||
break;
|
||||
@ -1542,7 +1587,8 @@
|
||||
}
|
||||
case 'clearevents': {
|
||||
events = [];
|
||||
events_update();
|
||||
updateEventsNaggle();
|
||||
//events_update();
|
||||
break;
|
||||
}
|
||||
case 'login': {
|
||||
@ -1601,7 +1647,7 @@
|
||||
function onRealNameCheckBox() {
|
||||
showRealNames = Q('RealNameCheckBox').checked;
|
||||
putstore("showRealNames", showRealNames ? 1 : 0);
|
||||
onSortSelectChange();
|
||||
onSortSelectChange(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1635,7 +1681,7 @@
|
||||
showRealNames = !showRealNames;
|
||||
Q('RealNameCheckBox').value = showRealNames;
|
||||
putstore("showRealNames", showRealNames ? 1 : 0);
|
||||
onSortSelectChange();
|
||||
onSortSelectChange(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
|
||||
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 { 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() {
|
||||
if (Q('d3coreMode').value == 1) {
|
||||
// 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) {
|
||||
// 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) {
|
||||
// Upload file as core
|
||||
p15uploadCore2();
|
||||
@ -5027,6 +5073,9 @@
|
||||
} else if (Q('d3coreMode').value == 5) {
|
||||
// Hard disconnect the mesh agent
|
||||
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 {
|
||||
// Upload server mesh agent code
|
||||
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] }); }
|
||||
}
|
||||
}
|
||||
|
||||
|
35
webserver.js
35
webserver.js
@ -754,7 +754,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
res.sendStatus(404); return;
|
||||
} else {
|
||||
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.usersGroups = req.connection.userGroups;
|
||||
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) {
|
||||
if (err != null) return;
|
||||
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) { }
|
||||
});
|
||||
}
|
||||
@ -2105,31 +2105,34 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
};
|
||||
|
||||
// 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;
|
||||
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
|
||||
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;
|
||||
|
||||
// Check we have agent rights
|
||||
var rights = user.links[agent.dbMeshKey].rights;
|
||||
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) {
|
||||
if (core == null) {
|
||||
if (coretype == 'clear') {
|
||||
// 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));
|
||||
} else if (core == '*') {
|
||||
} else if (coretype == 'default') {
|
||||
// Reset to 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.
|
||||
} else {
|
||||
agent.agentCoreCheck = 1000; // Tell the agent object we are not using a custom core.
|
||||
// Perform a SHA384 hash on the core module
|
||||
var hash = obj.crypto.createHash('sha384').update(Buffer.from(core, 'binary')).digest().toString('binary');
|
||||
|
||||
// Send the code module to the agent
|
||||
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + hash + core);
|
||||
} else if (coretype == 'recovery') {
|
||||
// Reset to recovery core
|
||||
agent.agentCoreCheck = 1001; // Tell the agent object we are using the recovery core.
|
||||
agent.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core hash.
|
||||
} else if (coretype == 'custom') {
|
||||
agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom 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
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user