mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
Server fixes, mesh agent download now has group name.
This commit is contained in:
parent
565722cfa9
commit
a28568f270
466
agents/agentrecoverycore.js
Normal file
466
agents/agentrecoverycore.js
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
|
||||||
|
var http = require('http');
|
||||||
|
var childProcess = require('child_process');
|
||||||
|
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore Recovery", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
||||||
|
var nextTunnelIndex = 1;
|
||||||
|
var tunnels = {};
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
//attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); });
|
||||||
|
|
||||||
|
function sendConsoleText(msg)
|
||||||
|
{
|
||||||
|
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg });
|
||||||
|
}
|
||||||
|
// Return p number of spaces
|
||||||
|
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
|
||||||
|
|
||||||
|
var path =
|
||||||
|
{
|
||||||
|
join: function ()
|
||||||
|
{
|
||||||
|
var x = [];
|
||||||
|
for (var i in arguments)
|
||||||
|
{
|
||||||
|
var w = arguments[i];
|
||||||
|
if (w != null)
|
||||||
|
{
|
||||||
|
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
|
||||||
|
}
|
||||||
|
x.push(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x.length == 0) return '/';
|
||||||
|
return x.join('/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Convert an object to string with all functions
|
||||||
|
function objToString(x, p, pad, ret) {
|
||||||
|
if (ret == undefined) ret = '';
|
||||||
|
if (p == undefined) p = 0;
|
||||||
|
if (x == null) { return '[null]'; }
|
||||||
|
if (p > 8) { return '[...]'; }
|
||||||
|
if (x == undefined) { return '[undefined]'; }
|
||||||
|
if (typeof x == 'string') { if (p == 0) return x; return '"' + x + '"'; }
|
||||||
|
if (typeof x == 'buffer') { return '[buffer]'; }
|
||||||
|
if (typeof x != 'object') { return x; }
|
||||||
|
var r = '{' + (ret ? '\r\n' : ' ');
|
||||||
|
for (var i in x) { if (i != '_ObjectID') { r += (addPad(p + 2, pad) + i + ': ' + objToString(x[i], p + 2, pad, ret) + (ret ? '\r\n' : ' ')); } }
|
||||||
|
return r + addPad(p, pad) + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// If there is a upload or download active on this connection, close the file
|
||||||
|
if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||||
|
if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
|
||||||
|
|
||||||
|
|
||||||
|
//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 is upload data, save it to file
|
||||||
|
if (this.httprequest.uploadFile)
|
||||||
|
{
|
||||||
|
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
|
||||||
|
this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.httprequest.protocol == 5)
|
||||||
|
{
|
||||||
|
// Process files commands
|
||||||
|
var cmd = null;
|
||||||
|
try { cmd = JSON.parse(data); } catch (e) { };
|
||||||
|
if (cmd == null) { return; }
|
||||||
|
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
|
||||||
|
if (cmd.action == undefined) { return; }
|
||||||
|
console.log('action: ', cmd.action);
|
||||||
|
|
||||||
|
//sendConsoleText('CMD: ' + JSON.stringify(cmd));
|
||||||
|
|
||||||
|
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
|
||||||
|
//console.log(objToString(cmd, 0, ' '));
|
||||||
|
switch (cmd.action)
|
||||||
|
{
|
||||||
|
case 'ls':
|
||||||
|
// Send the folder content to the browser
|
||||||
|
var response = getDirectoryInfo(cmd.path);
|
||||||
|
if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
|
||||||
|
this.write(new Buffer(JSON.stringify(response)));
|
||||||
|
break;
|
||||||
|
case 'mkdir': {
|
||||||
|
// Create a new empty folder
|
||||||
|
fs.mkdirSync(cmd.path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rm': {
|
||||||
|
// Delete, possibly recursive delete
|
||||||
|
for (var i in cmd.delfiles)
|
||||||
|
{
|
||||||
|
try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rename': {
|
||||||
|
// Rename a file or folder
|
||||||
|
var oldfullpath = path.join(cmd.path, cmd.oldname);
|
||||||
|
var newfullpath = path.join(cmd.path, cmd.newname);
|
||||||
|
try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'upload': {
|
||||||
|
// Upload a file, browser to agent
|
||||||
|
if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||||
|
if (cmd.path == undefined) break;
|
||||||
|
var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path;
|
||||||
|
try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
|
||||||
|
this.httprequest.uploadFileid = cmd.reqid;
|
||||||
|
if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'copy': {
|
||||||
|
// Copy a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'move': {
|
||||||
|
// Move a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a formated response for a given directory path
|
||||||
|
function getDirectoryInfo(reqpath)
|
||||||
|
{
|
||||||
|
var response = { path: reqpath, dir: [] };
|
||||||
|
if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
|
||||||
|
// List all the drives in the root, or the root itself
|
||||||
|
var results = null;
|
||||||
|
try { results = fs.readDrivesSync(); } catch (e) { } // TODO: Anyway to get drive total size and free space? Could draw a progress bar.
|
||||||
|
if (results != null) {
|
||||||
|
for (var i = 0; i < results.length; ++i) {
|
||||||
|
var drive = { n: results[i].name, t: 1 };
|
||||||
|
if (results[i].type == 'REMOVABLE') { drive.dt = 'removable'; } // TODO: See if this is USB/CDROM or something else, we can draw icons.
|
||||||
|
response.dir.push(drive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// List all the files and folders in this path
|
||||||
|
if (reqpath == '') { reqpath = '/'; }
|
||||||
|
var results = null, xpath = path.join(reqpath, '*');
|
||||||
|
//if (process.platform == "win32") { xpath = xpath.split('/').join('\\'); }
|
||||||
|
try { results = fs.readdirSync(xpath); } catch (e) { }
|
||||||
|
if (results != null) {
|
||||||
|
for (var i = 0; i < results.length; ++i) {
|
||||||
|
if ((results[i] != '.') && (results[i] != '..')) {
|
||||||
|
var stat = null, p = path.join(reqpath, results[i]);
|
||||||
|
//if (process.platform == "win32") { p = p.split('/').join('\\'); }
|
||||||
|
try { stat = fs.statSync(p); } catch (e) { } // TODO: Get file size/date
|
||||||
|
if ((stat != null) && (stat != undefined)) {
|
||||||
|
if (stat.isDirectory() == true) {
|
||||||
|
response.dir.push({ n: results[i], t: 2, d: stat.mtime });
|
||||||
|
} else {
|
||||||
|
response.dir.push({ n: results[i], t: 3, s: stat.size, d: stat.mtime });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
// Delete a directory with a files and directories within it
|
||||||
|
function deleteFolderRecursive(path, rec) {
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
if (rec == true) {
|
||||||
|
fs.readdirSync(path.join(path, '*')).forEach(function (file, index) {
|
||||||
|
var curPath = path.join(path, file);
|
||||||
|
if (fs.statSync(curPath).isDirectory()) { // recurse
|
||||||
|
deleteFolderRecursive(curPath, true);
|
||||||
|
} else { // delete file
|
||||||
|
fs.unlinkSync(curPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fs.unlinkSync(path);
|
||||||
|
}
|
||||||
|
};
|
@ -70,7 +70,7 @@ function createMeshCore(agent) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
||||||
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore v6", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore v6", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript, 32 = Temporary Agent, 64 = Recovery Agent
|
||||||
|
|
||||||
// Get the operating system description string
|
// Get the operating system description string
|
||||||
try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; }); } catch (ex) { }
|
try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; }); } catch (ex) { }
|
||||||
|
@ -223,7 +223,7 @@ module.exports.createTaskLimiterQueue = function (maxTasks, maxTaskTime, cleanin
|
|||||||
//console.log('PendingLaunch ' + id);
|
//console.log('PendingLaunch ' + id);
|
||||||
t.func(t.arg, id, obj); // Start the task
|
t.func(t.arg, id, obj); // Start the task
|
||||||
}
|
}
|
||||||
if ((obj.pending[0].length == 0) && (obj.pending[1].length == 0) && (obj.pending[2].length == 0) && (obj.timer != null)) {
|
if ((obj.currentCount == 0) && (obj.pending[0].length == 0) && (obj.pending[1].length == 0) && (obj.pending[2].length == 0) && (obj.timer != null)) {
|
||||||
// All done, clear the timer
|
// All done, clear the timer
|
||||||
clearInterval(obj.timer); obj.timer = null;
|
clearInterval(obj.timer); obj.timer = null;
|
||||||
}
|
}
|
||||||
|
56
meshagent.js
56
meshagent.js
@ -67,7 +67,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
obj.parent.parent.taskLimiter.completed(obj.agentUpdate.taskid); // Indicate this task complete
|
obj.parent.parent.taskLimiter.completed(obj.agentUpdate.taskid); // Indicate this task complete
|
||||||
obj.agentUpdate = null;
|
obj.agentUpdate = null;
|
||||||
}
|
}
|
||||||
if (((obj.agentInfo) && (obj.agentInfo.capabilities) && (obj.agentInfo.capabilities & 0x20)) || ((mesh) && (mesh.flags) && (mesh.flags & 1))) { // This is a temporary agent, remote it
|
|
||||||
|
// If this is a temporary or recovery agent, or all devices in this group are temporary, remove the agent (0x20 = Temporary, 0x40 = Recovery)
|
||||||
|
if (((obj.agentInfo) && (obj.agentInfo.capabilities) && ((obj.agentInfo.capabilities & 0x20) || (obj.agentInfo.capabilities & 0x40))) || ((mesh) && (mesh.flags) && (mesh.flags & 1))) {
|
||||||
// Delete this node including network interface information and events
|
// Delete this node including network interface information and events
|
||||||
obj.db.Remove(obj.dbNodeKey); // Remove node with that id
|
obj.db.Remove(obj.dbNodeKey); // Remove node with that id
|
||||||
obj.db.Remove('if' + obj.dbNodeKey); // Remove interface information
|
obj.db.Remove('if' + obj.dbNodeKey); // Remove interface information
|
||||||
@ -125,7 +127,14 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
|
|
||||||
// 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.
|
||||||
var 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 this is a recovery agent, use the agent recovery core
|
||||||
|
if (obj.agentInfo.capabilities & 0x40) { corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].arcore; }
|
||||||
|
|
||||||
|
// If the user asked, use the recovery core.
|
||||||
|
if (obj.agentCoreCheck == 1001) { corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].rcore; }
|
||||||
|
|
||||||
|
// If we have a core, use it.
|
||||||
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) {
|
||||||
@ -654,30 +663,45 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
if (disconnectCount > 4) {
|
if (disconnectCount > 4) {
|
||||||
// Too many disconnections, this agent has issues. Just clear the core.
|
// Too many disconnections, this agent has issues. Just clear the core.
|
||||||
obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0));
|
obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0));
|
||||||
console.log('Agent in trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.');
|
//console.log('Agent in trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.');
|
||||||
// TODO: Log or do something to recover?
|
// TODO: Log or do something to recover?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we need to make an native update check
|
if ((obj.agentInfo.capabilities & 64) != 0) {
|
||||||
obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
|
// This is a recovery agent
|
||||||
const corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core;
|
obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core hash.
|
||||||
if (corename == null) { obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0)); } // MeshCommand_CoreModule, ask mesh agent to clear the core
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
// Check the mesh core, if the agent is capable of running one
|
// Check if we need to make an native update check
|
||||||
if (((obj.agentInfo.capabilities & 16) != 0) && (corename != null)) {
|
obj.agentExeInfo = obj.parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
|
||||||
obj.send(obj.common.ShortToStr(11) + obj.common.ShortToStr(0)); // Command 11, ask for mesh core 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
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
agentCoreIsStable(); // No updates needed, agent is ready to go.
|
// 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.
|
||||||
|
} else {
|
||||||
|
agentCoreIsStable(); // No updates needed, agent is ready to go.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recoveryAgentCoreIsStable() {
|
||||||
|
// Recovery agent is doing ok, lets perform main agent checking.
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
console.log('recoveryAgentCoreIsStable()');
|
||||||
|
|
||||||
|
// Close the recovery agent connection when done.
|
||||||
|
obj.close(1);
|
||||||
|
}
|
||||||
|
|
||||||
function agentCoreIsStable() {
|
function agentCoreIsStable() {
|
||||||
// Check that the mesh exists
|
// Check that the mesh exists
|
||||||
var mesh = obj.parent.meshes[obj.dbMeshKey];
|
var mesh = obj.parent.meshes[obj.dbMeshKey];
|
||||||
@ -1009,7 +1033,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
if (command.name && (command.name != device.name)) { change = 1; log = 1; device.name = command.name; changes.push('name'); }
|
if (command.name && (command.name != device.name)) { change = 1; log = 1; device.name = command.name; changes.push('name'); }
|
||||||
if ((command.caps != null) && (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; } // Don't save this as an event to the db.
|
if ((command.caps != null) && (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; } // Don't save this as an event to the db.
|
||||||
if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; } // Allow Javascript on the agent to change all capabilities except console and javascript support, Don't save this as an event to the db.
|
if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; } // Allow Javascript on the agent to change all capabilities except console and javascript support, Don't save this as an event to the db.
|
||||||
if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; log = 1; changes.push('os desc'); }
|
if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; changes.push('os desc'); } // Don't save this as an event to the db.
|
||||||
if (command.intelamt) {
|
if (command.intelamt) {
|
||||||
if (!device.intelamt) { device.intelamt = {}; }
|
if (!device.intelamt) { device.intelamt = {}; }
|
||||||
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; log = 1; }
|
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; log = 1; }
|
||||||
|
@ -1140,6 +1140,16 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the agent recovery core if present
|
||||||
|
var meshAgentRecoveryCore = null;
|
||||||
|
if (obj.fs.existsSync(obj.path.join(__dirname, 'agents', 'agentrecoverycore.js')) == true) {
|
||||||
|
try { meshAgentRecoveryCore = obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'agentrecoverycore.js')).toString(); } catch (ex) { }
|
||||||
|
if (meshAgentRecoveryCore != null) {
|
||||||
|
modulesAdd['windows-agentrecovery'] = 'var addedModules = [];\r\n';
|
||||||
|
modulesAdd['linux-agentrecovery'] = '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) {
|
||||||
@ -1179,6 +1189,13 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
modulesAdd['windows-recovery'] += moduleData;
|
modulesAdd['windows-recovery'] += moduleData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge this module to agent recovery modules if needed
|
||||||
|
if (modulesAdd['windows-agentrecovery'] != null) {
|
||||||
|
if ((moduleName == 'win-console') || (moduleName == 'win-message-pump') || (moduleName == 'win-terminal')) {
|
||||||
|
modulesAdd['windows-agentrecovery'] += moduleData;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1187,6 +1204,8 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
for (var i in modulesAdd) {
|
for (var i in modulesAdd) {
|
||||||
if ((i == 'windows-recovery') || (i == 'linux-recovery')) {
|
if ((i == 'windows-recovery') || (i == 'linux-recovery')) {
|
||||||
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshRecoveryCore;
|
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshRecoveryCore;
|
||||||
|
} else if ((i == 'windows-agentrecovery') || (i == 'linux-agentrecovery')) {
|
||||||
|
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshAgentRecoveryCore;
|
||||||
} else {
|
} else {
|
||||||
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshCore;
|
obj.defaultMeshCores[i] = obj.common.IntToStr(0) + modulesAdd[i] + meshCore;
|
||||||
}
|
}
|
||||||
@ -1286,34 +1305,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', rcore: 'linux-recovery' },
|
0: { id: 0, localname: 'Unknown', rname: 'meshconsole.exe', desc: 'Unknown agent', update: false, amt: true, platform: 'unknown', core: 'linux-noamt', rcore: 'linux-recovery', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'windows-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'windows-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'windows-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'windows-agentrecovery' },
|
||||||
5: { id: 5, localname: 'meshagent_x86', rname: 'meshagent', desc: 'Linux x86-32', update: true, amt: true, platform: 'linux', core: 'linux-amt', rcore: 'linux-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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
7: { id: 7, localname: 'meshagent_mips', rname: 'meshagent', desc: 'Linux MIPS', update: true, amt: false, platform: 'linux', core: 'linux-noamt', 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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
9: { id: 9, localname: 'meshagent_arm', rname: 'meshagent', desc: 'Linux ARM5', update: true, amt: false, platform: 'linux', core: 'linux-noamt', 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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
13: { id: 13, localname: 'meshagent_pogo', rname: 'meshagent', desc: 'Linux ARM PogoPlug', 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', arcore: 'linux-agentrecovery' },
|
||||||
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
|
14: { id: 14, localname: 'MeshAgent-Android-APK', rname: 'meshandroid', desc: 'Android Market', update: false, amt: false, platform: 'android', core: 'linux-noamt', rcore: 'linux-recovery', arcore: 'linux-agentrecovery' }, // 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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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
|
17: { id: 17, localname: 'MeshAgent-ChromeOS', rname: 'meshagent', desc: 'Google ChromeOS', update: false, amt: false, platform: 'chromeos', core: 'linux-noamt', rcore: 'linux-recovery', arcore: 'linux-agentrecovery' }, // 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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'windows-agentrecovery' },
|
||||||
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' },
|
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', arcore: 'windows-agentrecovery' },
|
||||||
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
|
23: { id: 23, localname: 'MeshAgent-NodeJS', rname: 'meshagent', desc: 'NodeJS', update: false, amt: false, platform: 'node', core: 'linux-noamt', rcore: 'linux-recovery', arcore: 'linux-agentrecovery' }, // 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' },
|
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', arcore: 'linux-agentrecovery' },
|
||||||
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"
|
25: { id: 25, localname: 'meshagent_armhf', rname: 'meshagent', desc: 'Linux ARM - HardFloat', update: true, amt: false, platform: 'linux', core: 'linux-noamt', rcore: 'linux-recovery', arcore: 'linux-agentrecovery' }, // "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
|
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', arcore: 'linux-agentrecovery' }, // 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
|
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', arcore: 'linux-agentrecovery' } // Unsigned version of the Windows MeshAgent x64
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the list of available mesh agents
|
// Update the list of available mesh agents
|
||||||
|
24
meshuser.js
24
meshuser.js
@ -188,8 +188,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
"Connected Users": Object.keys(obj.parent.wssessions).length,
|
"Connected Users": Object.keys(obj.parent.wssessions).length,
|
||||||
"Users Sessions": Object.keys(obj.parent.wssessions2).length,
|
"Users Sessions": Object.keys(obj.parent.wssessions2).length,
|
||||||
"Relay Sessions": obj.parent.relaySessionCount,
|
"Relay Sessions": obj.parent.relaySessionCount,
|
||||||
"Relay Errors": obj.parent.relaySessionErrorCount
|
|
||||||
};
|
};
|
||||||
|
if (obj.parent.relaySessionErrorCount != 0) { serverStats['Relay Errors'] = obj.parent.relaySessionErrorCount; }
|
||||||
if (obj.parent.parent.mpsserver != null) { serverStats['Connected Intel® AMT'] = Object.keys(obj.parent.parent.mpsserver.ciraConnections).length; }
|
if (obj.parent.parent.mpsserver != null) { serverStats['Connected Intel® AMT'] = Object.keys(obj.parent.parent.mpsserver.ciraConnections).length; }
|
||||||
stats.values = { "Server State": serverStats }
|
stats.values = { "Server State": serverStats }
|
||||||
try { ws.send(JSON.stringify(stats)); } catch (ex) { }
|
try { ws.send(JSON.stringify(stats)); } catch (ex) { }
|
||||||
@ -462,7 +462,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 'help': {
|
case 'help': {
|
||||||
r = 'Available commands: help, args, resetserver, showconfig, usersessions.';
|
r = 'Available commands: help, args, resetserver, showconfig, usersessions, tasklimiter, cores.';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'args': {
|
case 'args': {
|
||||||
@ -485,6 +485,26 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'tasklimiter': {
|
||||||
|
if (obj.parent.parent.taskLimiter != null) {
|
||||||
|
//var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null };
|
||||||
|
const tl = obj.parent.parent.taskLimiter;
|
||||||
|
r += 'MaxTasks: ' + tl.maxTasks + '<br />';
|
||||||
|
r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds<br />';
|
||||||
|
r += 'NextTaskId: ' + tl.nextTaskId + '<br />';
|
||||||
|
r += 'CurrentCount: ' + tl.currentCount + '<br />';
|
||||||
|
var c = [];
|
||||||
|
for (var i in tl.current) { c.push(i); }
|
||||||
|
r += 'Current: [' + c.join(', ') + ']<br />';
|
||||||
|
r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '<br />';
|
||||||
|
r += 'Timer: ' + (tl.timer != null) + '<br />';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'cores': {
|
||||||
|
if (obj.parent.parent.defaultMeshCores != null) { for (var i in obj.parent.parent.defaultMeshCores) { r += i + ': ' + obj.parent.parent.defaultMeshCores[i].length + ' bytes<br />'; } }
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'showconfig': {
|
case 'showconfig': {
|
||||||
// Make a copy of the configuration and hide any secrets
|
// Make a copy of the configuration and hide any secrets
|
||||||
var config = obj.common.Clone(obj.parent.parent.config);
|
var config = obj.common.Clone(obj.parent.parent.config);
|
||||||
|
File diff suppressed because one or more lines are too long
@ -2463,13 +2463,17 @@
|
|||||||
x += addHtmlValue('Installation Type', '<select id=aginsType onchange=addAgentToMeshClick() style=width:236px><option value=0>Background & interactive</option><option value=2>Background only</option><option value=1>Interactive only</option></select>');
|
x += addHtmlValue('Installation Type', '<select id=aginsType onchange=addAgentToMeshClick() style=width:236px><option value=0>Background & interactive</option><option value=2>Background only</option><option value=1>Interactive only</option></select>');
|
||||||
x += '</div><hr>';
|
x += '</div><hr>';
|
||||||
|
|
||||||
|
// \/:*?"<>|
|
||||||
|
var meshfilename = mesh.name
|
||||||
|
meshfilename = meshfilename.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join('');
|
||||||
|
|
||||||
// Windows agent install
|
// Windows agent install
|
||||||
//x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and configuration file and install the agent on the computer to manage.<br /><br />";
|
//x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and configuration file and install the agent on the computer to manage.<br /><br />";
|
||||||
x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and install it the computer to manage. This agent has server and mesh information embedded within it.<br /><br />";
|
x += "<div id=agins_windows>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and install it the computer to manage. This agent has server and mesh information embedded within it.<br /><br />";
|
||||||
//x += addHtmlValue('Mesh Agent', '<a id=aginsw32lnk href="meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank" title="32bit version of the MeshAgent">Windows (.exe)</a>');
|
//x += addHtmlValue('Mesh Agent', '<a id=aginsw32lnk href="meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank" title="32bit version of the MeshAgent">Windows (.exe)</a>');
|
||||||
//x += addHtmlValue('Mesh Agent', '<a id=aginsw64lnk href="meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank" title="64bit version of the MeshAgent">Windows x64 (.exe)</a>');
|
//x += addHtmlValue('Mesh Agent', '<a id=aginsw64lnk href="meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank" title="64bit version of the MeshAgent">Windows x64 (.exe)</a>');
|
||||||
x += addHtmlValue('Mesh Agent', '<a id=aginsw32lnk style=cursor:pointer onclick=fileDownload("meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=","MeshAgent.exe",1) title="32bit version of the MeshAgent">Windows (.exe)</a>');
|
x += addHtmlValue('Mesh Agent', '<a id=aginsw32lnk style=cursor:pointer onclick=fileDownload("meshagents?id=3&meshid=' + meshid.split('/')[2] + '&installflags=","MeshAgent-' + meshfilename + '.exe",1) title="32bit version of the MeshAgent">Windows (.exe)</a>');
|
||||||
x += addHtmlValue('Mesh Agent', '<a id=aginsw64lnk style=cursor:pointer onclick=fileDownload("meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=","MeshAgent.exe",1) title="64bit version of the MeshAgent">Windows x64 (.exe)</a>');
|
x += addHtmlValue('Mesh Agent', '<a id=aginsw64lnk style=cursor:pointer onclick=fileDownload("meshagents?id=4&meshid=' + meshid.split('/')[2] + '&installflags=","MeshAgent-' + meshfilename + '.exe",1) title="64bit version of the MeshAgent">Windows x64 (.exe)</a>');
|
||||||
if (debugmode > 0) { x += addHtmlValue('Settings File', '<a id=aginswmshlnk href="meshsettings?id=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank">' + EscapeHtml(mesh.name) + ' settings (.msh)</a>'); }
|
if (debugmode > 0) { x += addHtmlValue('Settings File', '<a id=aginswmshlnk href="meshsettings?id=' + meshid.split('/')[2] + '&installflags=0" rel="noreferrer noopener" target="_blank">' + EscapeHtml(mesh.name) + ' settings (.msh)</a>'); }
|
||||||
x += "</div>";
|
x += "</div>";
|
||||||
|
|
||||||
@ -2529,7 +2533,7 @@
|
|||||||
xdr.open("GET", window.location.href + path + flag);
|
xdr.open("GET", window.location.href + path + flag);
|
||||||
xdr.timeout = 15000;
|
xdr.timeout = 15000;
|
||||||
xdr.responseType = "blob";
|
xdr.responseType = "blob";
|
||||||
xdr.onprogress = function (x) { console.log(x); };
|
xdr.onprogress = function (x) { /*console.log(x);*/ };
|
||||||
xdr.onload = function (e) { saveAs(new Blob([e.target.response], { type: "application/octet-stream" }), name); if (xxdialogTag == 'fileDownload') { setDialogMode(0); } };
|
xdr.onload = function (e) { saveAs(new Blob([e.target.response], { type: "application/octet-stream" }), name); if (xxdialogTag == 'fileDownload') { setDialogMode(0); } };
|
||||||
xdr.onerror = function () { if (xxdialogTag == 'fileDownload') { setDialogMode(0); } alert('Agent downloads timeout.'); };
|
xdr.onerror = function () { if (xxdialogTag == 'fileDownload') { setDialogMode(0); } alert('Agent downloads timeout.'); };
|
||||||
xdr.ontimeout = function () { if (xxdialogTag == 'fileDownload') { setDialogMode(0); } alert('Unable to download agent.'); };
|
xdr.ontimeout = function () { if (xxdialogTag == 'fileDownload') { setDialogMode(0); } alert('Unable to download agent.'); };
|
||||||
|
Loading…
Reference in New Issue
Block a user