1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-02-12 19:11:51 +00:00

Updated meshcores.

This commit is contained in:
Ylian Saint-Hilaire 2021-01-18 16:11:15 -08:00
commit 67fd1e7825
2 changed files with 832 additions and 1507 deletions

File diff suppressed because it is too large Load diff

View file

@ -6,11 +6,9 @@ var nextTunnelIndex = 1;
var tunnels = {}; var tunnels = {};
var fs = require('fs'); var fs = require('fs');
if (require('MeshAgent').ARCHID == null) if (require('MeshAgent').ARCHID == null) {
{
var id = null; var id = null;
switch (process.platform) switch (process.platform) {
{
case 'win32': case 'win32':
id = require('_GenericMarshal').PointerSize == 4 ? 3 : 4; id = require('_GenericMarshal').PointerSize == 4 ? 3 : 4;
break; break;
@ -18,12 +16,10 @@ if (require('MeshAgent').ARCHID == null)
id = require('_GenericMarshal').PointerSize == 4 ? 31 : 30; id = require('_GenericMarshal').PointerSize == 4 ? 31 : 30;
break; break;
case 'darwin': case 'darwin':
try try {
{
id = require('os').arch() == 'x64' ? 16 : 29; id = require('os').arch() == 'x64' ? 16 : 29;
} }
catch(xx) catch (xx) {
{
id = 16; id = 16;
} }
break; break;
@ -33,22 +29,17 @@ if (require('MeshAgent').ARCHID == null)
//attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); }); //attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); });
function sendConsoleText(msg, sessionid) function sendConsoleText(msg, sessionid) {
{ if (sessionid != null) {
if (sessionid != null)
{
require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: msg, sessionid: sessionid }); require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: msg, sessionid: sessionid });
} }
else else {
{
require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: msg }); require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: msg });
} }
} }
function sendAgentMessage(msg, icon) function sendAgentMessage(msg, icon) {
{ if (sendAgentMessage.messages == null) {
if (sendAgentMessage.messages == null)
{
sendAgentMessage.messages = {}; sendAgentMessage.messages = {};
sendAgentMessage.nextid = 1; sendAgentMessage.nextid = 1;
} }
@ -57,11 +48,9 @@ function sendAgentMessage(msg, icon)
} }
// Add to the server event log // Add to the server event log
function MeshServerLog(msg, state) function MeshServerLog(msg, state) {
{
if (typeof msg == 'string') { msg = { action: 'log', msg: msg }; } else { msg.action = 'log'; } if (typeof msg == 'string') { msg = { action: 'log', msg: msg }; } else { msg.action = 'log'; }
if (state) if (state) {
{
if (state.userid) { msg.userid = state.userid; } if (state.userid) { msg.userid = state.userid; }
if (state.username) { msg.username = state.username; } if (state.username) { msg.username = state.username; }
if (state.sessionid) { msg.sessionid = state.sessionid; } if (state.sessionid) { msg.sessionid = state.sessionid; }
@ -71,11 +60,9 @@ function MeshServerLog(msg, state)
} }
// Add to the server event log, use internationalized events // Add to the server event log, use internationalized events
function MeshServerLogEx(id, args, msg, state) function MeshServerLogEx(id, args, msg, state) {
{
var msg = { action: 'log', msgid: id, msgArgs: args, msg: msg }; var msg = { action: 'log', msgid: id, msgArgs: args, msg: msg };
if (state) if (state) {
{
if (state.userid) { msg.userid = state.userid; } if (state.userid) { msg.userid = state.userid; }
if (state.username) { msg.username = state.username; } if (state.username) { msg.username = state.username; }
if (state.sessionid) { msg.sessionid = state.sessionid; } if (state.sessionid) { msg.sessionid = state.sessionid; }
@ -84,17 +71,13 @@ function MeshServerLogEx(id, args, msg, state)
require('MeshAgent').SendCommand(msg); require('MeshAgent').SendCommand(msg);
} }
function pathjoin() function pathjoin() {
{
var x = []; var x = [];
for (var i in arguments) for (var i in arguments) {
{
var w = arguments[i]; var w = arguments[i];
if (w != null) if (w != null) {
{
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
if (i != 0) if (i != 0) {
{
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
} }
x.push(w); x.push(w);
@ -106,9 +89,70 @@ function pathjoin()
// Replace a string with a number if the string is an exact number // Replace a string with a number if the string is an exact number
function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) === x)) { x = parseInt(x); } return x; } function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) === x)) { x = parseInt(x); } return x; }
function linux_execv(name, agentfilename, sessionid) {
var libs = require('monitor-info').getLibInfo('libc');
var libc = null;
function bsd_execv(name, agentfilename, sessionid) while (libs.length > 0) {
{ try {
libc = require('_GenericMarshal').CreateNativeProxy(libs.pop().path);
break;
}
catch (e) {
libc = null;
continue;
}
}
if (libc != null) {
try {
libc.CreateMethod('execv');
}
catch (e) {
libc = null;
}
}
if (libc == null) {
// Couldn't find libc.so, fallback to using service manager to restart agent
if (sessionid != null) { sendConsoleText('Restarting service via service-manager...', sessionid) }
try {
// restart service
var s = require('service-manager').manager.getService(name);
s.restart();
}
catch (zz) {
sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
sendAgentMessage('Self Update encountered an error trying to restart service', 3);
}
return;
}
if (sessionid != null) { sendConsoleText('Restarting service via execv()...', sessionid) }
var i;
var args;
var argarr = [];
var path = require('_GenericMarshal').CreateVariable(process.execPath);
if (require('MeshAgent').getStartupOptions != null) {
var options = require('MeshAgent').getStartupOptions();
for (i in options) {
argarr.push('--' + i + '="' + options[i] + '"');
}
}
args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
for (i = 0; i < argarr.length; ++i) {
var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
}
libc.execv(path, args);
if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
sendAgentMessage('Self Update failed because execv() failed', 3);
}
function bsd_execv(name, agentfilename, sessionid) {
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); }); child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); }); child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
@ -123,21 +167,18 @@ function bsd_execv(name, agentfilename, sessionid)
child.stdin.write(' }'); child.stdin.write(' }');
child.stdin.write("}'\nexit\n"); child.stdin.write("}'\nexit\n");
child.waitExit(); child.waitExit();
if (child.stdout.str.trim() == '') if (child.stdout.str.trim() == '') {
{
if (sessionid != null) { sendConsoleText('Self Update failed because cannot find libc.so', sessionid) } if (sessionid != null) { sendConsoleText('Self Update failed because cannot find libc.so', sessionid) }
sendAgentMessage('Self Update failed because cannot find libc.so', 3); sendAgentMessage('Self Update failed because cannot find libc.so', 3);
return; return;
} }
var libc = null; var libc = null;
try try {
{
libc = require('_GenericMarshal').CreateNativeProxy(child.stdout.str.trim()); libc = require('_GenericMarshal').CreateNativeProxy(child.stdout.str.trim());
libc.CreateMethod('execv'); libc.CreateMethod('execv');
} }
catch(e) catch (e) {
{
if (sessionid != null) { sendConsoleText('Self Update failed: ' + e.toString(), sessionid) } if (sessionid != null) { sendConsoleText('Self Update failed: ' + e.toString(), sessionid) }
sendAgentMessage('Self Update failed: ' + e.toString(), 3); sendAgentMessage('Self Update failed: ' + e.toString(), 3);
return; return;
@ -148,32 +189,28 @@ function bsd_execv(name, agentfilename, sessionid)
var argarr = []; var argarr = [];
var args; var args;
var options = require('MeshAgent').getStartupOptions(); var options = require('MeshAgent').getStartupOptions();
for(i in options) for (i in options) {
{
argarr.push('--' + i + '="' + options[i] + '"'); argarr.push('--' + i + '="' + options[i] + '"');
} }
args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize); args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
for (i = 0; i < argarr.length; ++i) for (i = 0; i < argarr.length; ++i) {
{
var arg = require('_GenericMarshal').CreateVariable(argarr[i]); var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize); arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
} }
if (sessionid != null) { sendConsoleText('Restarting service via service-manager', sessionid) }
libc.execv(path, args); libc.execv(path, args);
if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) } if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
sendAgentMessage('Self Update failed because execv() failed', 3); sendAgentMessage('Self Update failed because execv() failed', 3);
} }
function windows_execve(name, agentfilename, sessionid) function windows_execve(name, agentfilename, sessionid) {
{
var libc; var libc;
try try {
{
libc = require('_GenericMarshal').CreateNativeProxy('msvcrt.dll'); libc = require('_GenericMarshal').CreateNativeProxy('msvcrt.dll');
libc.CreateMethod('_wexecve'); libc.CreateMethod('_wexecve');
} }
catch (xx) catch (xx) {
{
sendConsoleText('Self Update failed because msvcrt.dll is missing', sessionid); sendConsoleText('Self Update failed because msvcrt.dll is missing', sessionid);
sendAgentMessage('Self Update failed because msvcrt.dll is missing', 3); sendAgentMessage('Self Update failed because msvcrt.dll is missing', 3);
return; return;
@ -191,43 +228,33 @@ function windows_execve(name, agentfilename, sessionid)
} }
// Start a JavaScript based Agent Self-Update // Start a JavaScript based Agent Self-Update
function agentUpdate_Start(updateurl, updateoptions) function agentUpdate_Start(updateurl, updateoptions) {
{
sendConsoleText('agentUpdate_Start: ' + updateurl + ', ' + JSON.stringify(updateoptions));
// If this value is null // If this value is null
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
if (this._selfupdate != null) if (this._selfupdate != null) {
{
// We were already called, so we will ignore this duplicate request // We were already called, so we will ignore this duplicate request
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); } if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
} }
else else {
{ if (require('MeshAgent').ARCHID == null && updateurl == null) {
if (require('MeshAgent').ARCHID == null && updateurl == null)
{
// This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull // This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid); sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
} }
else else {
{
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
var name = require('MeshAgent').serviceName; var name = require('MeshAgent').serviceName;
if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; } // This is an older agent that doesn't expose the service name, so use the default if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; } // This is an older agent that doesn't expose the service name, so use the default
try try {
{
var s = require('service-manager').manager.getService(name); var s = require('service-manager').manager.getService(name);
if (!s.isMe()) if (!s.isMe()) {
{
if (process.platform == 'win32') { s.close(); } if (process.platform == 'win32') { s.close(); }
sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid); sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
return; return;
} }
if (process.platform == 'win32') { s.close(); } if (process.platform == 'win32') { s.close(); }
} }
catch (zz) catch (zz) {
{
sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid); sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3); sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
return; return;
@ -238,65 +265,47 @@ function agentUpdate_Start(updateurl, updateoptions)
options.protocol = 'https:'; options.protocol = 'https:';
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); } if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
options.rejectUnauthorized = false; options.rejectUnauthorized = false;
options.checkServerIdentity = function checkServerIdentity(certs) options.checkServerIdentity = function checkServerIdentity(certs) {
{
// If the tunnel certificate matches the control channel certificate, accept the connection // If the tunnel certificate matches the control channel certificate, accept the connection
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { } try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { } try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
// Check that the certificate is the one expected by the server, fail if not. // Check that the certificate is the one expected by the server, fail if not.
sendConsoleText('hashx: ' + checkServerIdentity.servertlshash);
if (checkServerIdentity.servertlshash == null) { if (checkServerIdentity.servertlshash == null) {
sendConsoleText('1a');
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; } if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
sendConsoleText('1b');
sendConsoleText('Self Update failed, because the url cannot be verified', sessionid); sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
sendAgentMessage('Self Update failed, because the url cannot be verified', 3); sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
throw new Error('BadCert'); throw new Error('BadCert');
} }
sendConsoleText('2t: ' + checkServerIdentity.servertlshash); if (certs[0].digest == null) { return; }
sendConsoleText('2y: ' + checkServerIdentity.servertlshash.toLowerCase());
sendConsoleText('2z: ' + certs[0].digest);
sendConsoleText('2r: ' + certs[0].fingerprint);
if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) { if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) {
sendConsoleText('2b');
sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid); sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3); sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
throw new Error('BadCert') throw new Error('BadCert')
} }
sendConsoleText('3');
} }
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null); options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
sendConsoleText('Downloading1: ' + JSON.stringify(options));
sendConsoleText('Downloading2: ' + JSON.stringify(updateoptions));
this._selfupdate = require('https').get(options); this._selfupdate = require('https').get(options);
this._selfupdate.on('error', function (e) this._selfupdate.on('error', function (e) {
{
sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid); sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3); sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
}); });
this._selfupdate.on('response', function (img) this._selfupdate.on('response', function (img) {
{
this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' }); this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' });
this._filehash = require('SHA384Stream').create(); this._filehash = require('SHA384Stream').create();
this._filehash.on('hash', function (h) this._filehash.on('hash', function (h) {
{ if (updateoptions != null && updateoptions.hash != null) {
if (updateoptions != null && updateoptions.hash != null) if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase()) {
{
if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
{
if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); } if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); }
} }
else else {
{
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check', sessionid); sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check', sessionid);
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3); sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
return; return;
} }
} }
else else {
{
sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid); sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
} }
@ -304,13 +313,11 @@ function agentUpdate_Start(updateurl, updateoptions)
try { require('MeshAgent').SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { } try { require('MeshAgent').SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { }
if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); } if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); }
if (process.platform == 'win32') if (process.platform == 'win32') {
{
// Use _wexecve() equivalent to perform the update // Use _wexecve() equivalent to perform the update
windows_execve(name, agentfilename, sessionid); windows_execve(name, agentfilename, sessionid);
} }
else else {
{
var m = require('fs').statSync(process.execPath).mode; var m = require('fs').statSync(process.execPath).mode;
require('fs').chmodSync(process.cwd() + agentfilename + '.update', m); require('fs').chmodSync(process.cwd() + agentfilename + '.update', m);
@ -324,24 +331,24 @@ function agentUpdate_Start(updateurl, updateoptions)
// erase update // erase update
require('fs').unlinkSync(process.cwd() + agentfilename + '.update'); require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
if (sessionid != null) { sendConsoleText('Restarting service...', sessionid); } switch (process.platform) {
if (process.platform == 'freebsd') case 'freebsd':
{
bsd_execv(name, agentfilename, sessionid); bsd_execv(name, agentfilename, sessionid);
} break;
else case 'linux':
{ linux_execv(name, agentfilename, sessionid);
try break;
{ default:
try {
// restart service // restart service
var s = require('service-manager').manager.getService(name); var s = require('service-manager').manager.getService(name);
s.restart(); s.restart();
} }
catch (zz) catch (zz) {
{
sendConsoleText('Self Update encountered an error trying to restart service', sessionid); sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
sendAgentMessage('Self Update encountered an error trying to restart service', 3); sendAgentMessage('Self Update encountered an error trying to restart service', 3);
} }
break;
} }
} }
}); });
@ -396,18 +403,14 @@ function splitArgs(str) {
} }
// Parse arguments string array into an object // Parse arguments string array into an object
function parseArgs(argv) function parseArgs(argv) {
{
var results = { '_': [] }, current = null; var results = { '_': [] }, current = null;
for (var i = 1, len = argv.length; i < len; i++) for (var i = 1, len = argv.length; i < len; i++) {
{
var x = argv[i]; var x = argv[i];
if (x.length > 2 && x[0] == '-' && x[1] == '-') if (x.length > 2 && x[0] == '-' && x[1] == '-') {
{
if (current != null) { results[current] = true; } if (current != null) { results[current] = true; }
current = x.substring(2); current = x.substring(2);
} else } else {
{
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); } if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
} }
} }
@ -440,8 +443,7 @@ require('MeshAgent').on('Connected', function () {
}); });
// Called when receiving control data on websocket // Called when receiving control data on websocket
function onTunnelControlData(data, ws) function onTunnelControlData(data, ws) {
{
var obj; var obj;
if (ws == null) { ws = this; } if (ws == null) { ws = this; }
if (typeof data == 'string') { try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON: ' + data); return; } } if (typeof data == 'string') { try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON: ' + data); return; } }
@ -449,16 +451,12 @@ function onTunnelControlData(data, ws)
//sendConsoleText('onTunnelControlData(' + ws.httprequest.protocol + '): ' + JSON.stringify(data)); //sendConsoleText('onTunnelControlData(' + ws.httprequest.protocol + '): ' + JSON.stringify(data));
//console.log('onTunnelControlData: ' + JSON.stringify(data)); //console.log('onTunnelControlData: ' + JSON.stringify(data));
if (obj.action) if (obj.action) {
{ switch (obj.action) {
switch (obj.action)
{
case 'lock': { case 'lock': {
// Lock the current user out of the desktop // Lock the current user out of the desktop
try try {
{ if (process.platform == 'win32') {
if (process.platform == 'win32')
{
MeshServerLog("Locking remote user out of desktop", ws.httprequest); MeshServerLog("Locking remote user out of desktop", ws.httprequest);
var child = require('child_process'); var child = require('child_process');
child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'RunDll32.exe user32.dll,LockWorkStation'], { type: 1 }); child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'RunDll32.exe user32.dll,LockWorkStation'], { type: 1 });
@ -473,8 +471,7 @@ function onTunnelControlData(data, ws)
return; return;
} }
switch (obj.type) switch (obj.type) {
{
case 'options': { case 'options': {
// These are additional connection options passed in the control channel. // These are additional connection options passed in the control channel.
//sendConsoleText('options: ' + JSON.stringify(obj)); //sendConsoleText('options: ' + JSON.stringify(obj));
@ -494,13 +491,11 @@ function onTunnelControlData(data, ws)
} }
case 'termsize': { case 'termsize': {
// Indicates a change in terminal size // Indicates a change in terminal size
if (process.platform == 'win32') if (process.platform == 'win32') {
{
if (ws.httprequest._dispatcher == null) return; if (ws.httprequest._dispatcher == null) return;
if (ws.httprequest._dispatcher.invoke) { ws.httprequest._dispatcher.invoke('resizeTerminal', [obj.cols, obj.rows]); } if (ws.httprequest._dispatcher.invoke) { ws.httprequest._dispatcher.invoke('resizeTerminal', [obj.cols, obj.rows]); }
} }
else else {
{
if (ws.httprequest.process == null || ws.httprequest.process.pty == 0) return; if (ws.httprequest.process == null || ws.httprequest.process.pty == 0) return;
if (ws.httprequest.process.tcsetsize) { ws.httprequest.process.tcsetsize(obj.rows, obj.cols); } if (ws.httprequest.process.tcsetsize) { ws.httprequest.process.tcsetsize(obj.rows, obj.cols); }
} }
@ -510,23 +505,18 @@ function onTunnelControlData(data, ws)
} }
require('MeshAgent').AddCommandHandler(function (data) require('MeshAgent').AddCommandHandler(function (data) {
{ if (typeof data == 'object') {
if (typeof data == 'object')
{
// If this is a console command, parse it and call the console handler // If this is a console command, parse it and call the console handler
switch (data.action) switch (data.action) {
{
case 'agentupdate': case 'agentupdate':
agentUpdate_Start(data.url, { hash: data.hash, tlshash: data.servertlshash, sessionid: data.sessionid }); agentUpdate_Start(data.url, { hash: data.hash, tlshash: data.servertlshash, sessionid: data.sessionid });
break; break;
case 'msg': case 'msg':
{ {
switch (data.type) switch (data.type) {
{
case 'console': { // Process a console command case 'console': { // Process a console command
if (data.value && data.sessionid) if (data.value && data.sessionid) {
{
var args = splitArgs(data.value); var args = splitArgs(data.value);
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid); processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
} }
@ -534,23 +524,19 @@ require('MeshAgent').AddCommandHandler(function (data)
} }
case 'tunnel': case 'tunnel':
{ {
if (data.value != null) if (data.value != null) { // Process a new tunnel connection request
{ // Process a new tunnel connection request
// Create a new tunnel object // Create a new tunnel object
if (data.rights != 4294967295) if (data.rights != 4294967295) {
{
MeshServerLog('Tunnel Error: RecoveryCore requires admin rights for tunnels'); MeshServerLog('Tunnel Error: RecoveryCore requires admin rights for tunnels');
break; break;
} }
var xurl = getServerTargetUrlEx(data.value); var xurl = getServerTargetUrlEx(data.value);
if (xurl != null) if (xurl != null) {
{
var woptions = http.parseUri(xurl); var woptions = http.parseUri(xurl);
woptions.rejectUnauthorized = 0; woptions.rejectUnauthorized = 0;
woptions.perMessageDeflate = false; woptions.perMessageDeflate = false;
woptions.checkServerIdentity = function checkServerIdentity(certs) woptions.checkServerIdentity = function checkServerIdentity(certs) {
{
// If the tunnel certificate matches the control channel certificate, accept the connection // If the tunnel certificate matches the control channel certificate, accept the connection
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { } try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { } try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
@ -563,13 +549,10 @@ require('MeshAgent').AddCommandHandler(function (data)
//sendConsoleText(JSON.stringify(woptions)); //sendConsoleText(JSON.stringify(woptions));
var tunnel = http.request(woptions); var tunnel = http.request(woptions);
tunnel.on('upgrade', function (response, s, head) tunnel.on('upgrade', function (response, s, head) {
{ if (require('MeshAgent').idleTimeout != null) {
if (require('MeshAgent').idleTimeout != null)
{
s.setTimeout(require('MeshAgent').idleTimeout * 1000); s.setTimeout(require('MeshAgent').idleTimeout * 1000);
s.on('timeout', function () s.on('timeout', function () {
{
this.ping(); this.ping();
this.setTimeout(require('MeshAgent').idleTimeout * 1000); this.setTimeout(require('MeshAgent').idleTimeout * 1000);
}); });
@ -578,8 +561,7 @@ require('MeshAgent').AddCommandHandler(function (data)
this.s = s; this.s = s;
s.httprequest = this; s.httprequest = this;
s.tunnel = this; s.tunnel = this;
s.on('end', function () s.on('end', function () {
{
if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls. 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 there is a upload or download active on this connection, close the file
@ -592,18 +574,14 @@ require('MeshAgent').AddCommandHandler(function (data)
// Clean up WebSocket // Clean up WebSocket
this.removeAllListeners('data'); this.removeAllListeners('data');
}); });
s.on('data', function (data) s.on('data', function (data) {
{
// If this is upload data, save it to file // If this is upload data, save it to file
if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123)) if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123)) {
{
// Save the data to file being uploaded. // Save the data to file being uploaded.
if (data[0] == 0) if (data[0] == 0) {
{
// If data starts with zero, skip the first byte. This is used to escape binary file data from JSON. // If data starts with zero, skip the first byte. This is used to escape binary file data from JSON.
try { fs.writeSync(this.httprequest.uploadFile, data, 1, data.length - 1); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out. try { fs.writeSync(this.httprequest.uploadFile, data, 1, data.length - 1); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
} else } else {
{
// If data does not start with zero, save as-is. // If data does not start with zero, save as-is.
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out. try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
} }
@ -611,22 +589,18 @@ require('MeshAgent').AddCommandHandler(function (data)
return; return;
} }
if (this.httprequest.state == 0) if (this.httprequest.state == 0) {
{
// Check if this is a relay connection // Check if this is a relay connection
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; /*sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid);*/ } if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; /*sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid);*/ }
} }
else else {
{
// Handle tunnel data // Handle tunnel data
if (this.httprequest.protocol == 0) if (this.httprequest.protocol == 0) { // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user), 10 = FileTransfer
{ // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user), 10 = FileTransfer
// Take a look at the protocol // Take a look at the protocol
if ((data.length > 3) && (data[0] == '{')) { onTunnelControlData(data, this); return; } if ((data.length > 3) && (data[0] == '{')) { onTunnelControlData(data, this); return; }
this.httprequest.protocol = parseInt(data); this.httprequest.protocol = parseInt(data);
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; } if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
if (this.httprequest.protocol == 10) if (this.httprequest.protocol == 10) {
{
// //
// Basic file transfer // Basic file transfer
// //
@ -634,50 +608,42 @@ require('MeshAgent').AddCommandHandler(function (data)
if ((process.platform != 'win32') && (this.httprequest.xoptions.file.startsWith('/') == false)) { this.httprequest.xoptions.file = '/' + this.httprequest.xoptions.file; } if ((process.platform != 'win32') && (this.httprequest.xoptions.file.startsWith('/') == false)) { this.httprequest.xoptions.file = '/' + this.httprequest.xoptions.file; }
try { stats = require('fs').statSync(this.httprequest.xoptions.file) } catch (e) { } try { stats = require('fs').statSync(this.httprequest.xoptions.file) } catch (e) { }
try { if (stats) { this.httprequest.downloadFile = fs.createReadStream(this.httprequest.xoptions.file, { flags: 'rbN' }); } } catch (e) { } try { if (stats) { this.httprequest.downloadFile = fs.createReadStream(this.httprequest.xoptions.file, { flags: 'rbN' }); } } catch (e) { }
if (this.httprequest.downloadFile) if (this.httprequest.downloadFile) {
{
//sendConsoleText('BasicFileTransfer, ok, ' + this.httprequest.xoptions.file + ', ' + JSON.stringify(stats)); //sendConsoleText('BasicFileTransfer, ok, ' + this.httprequest.xoptions.file + ', ' + JSON.stringify(stats));
this.write(JSON.stringify({ op: 'ok', size: stats.size })); this.write(JSON.stringify({ op: 'ok', size: stats.size }));
this.httprequest.downloadFile.pipe(this); this.httprequest.downloadFile.pipe(this);
this.httprequest.downloadFile.end = function () { } this.httprequest.downloadFile.end = function () { }
} else } else {
{
//sendConsoleText('BasicFileTransfer, cancel, ' + this.httprequest.xoptions.file); //sendConsoleText('BasicFileTransfer, cancel, ' + this.httprequest.xoptions.file);
this.write(JSON.stringify({ op: 'cancel' })); this.write(JSON.stringify({ op: 'cancel' }));
} }
} }
else if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6) || (this.httprequest.protocol == 8) || (this.httprequest.protocol == 9)) else if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6) || (this.httprequest.protocol == 8) || (this.httprequest.protocol == 9)) {
{
// //
// Remote Terminal // Remote Terminal
// //
if (process.platform == "win32") if (process.platform == "win32") {
{
var cols = 80, rows = 25; var cols = 80, rows = 25;
if (this.httprequest.xoptions) if (this.httprequest.xoptions) {
{
if (this.httprequest.xoptions.rows) { rows = this.httprequest.xoptions.rows; } if (this.httprequest.xoptions.rows) { rows = this.httprequest.xoptions.rows; }
if (this.httprequest.xoptions.cols) { cols = this.httprequest.xoptions.cols; } if (this.httprequest.xoptions.cols) { cols = this.httprequest.xoptions.cols; }
} }
// Admin Terminal // Admin Terminal
if (require('win-virtual-terminal').supported) if (require('win-virtual-terminal').supported) {
{
// ConPTY PseudoTerminal // ConPTY PseudoTerminal
// this.httprequest._term = require('win-virtual-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](80, 25); // this.httprequest._term = require('win-virtual-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](80, 25);
// The above line is commented out, because there is a bug with ClosePseudoConsole() API, so this is the workaround // The above line is commented out, because there is a bug with ClosePseudoConsole() API, so this is the workaround
this.httprequest._dispatcher = require('win-dispatcher').dispatch({ modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: 'Start', args: [cols, rows] } }); this.httprequest._dispatcher = require('win-dispatcher').dispatch({ modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: 'Start', args: [cols, rows] } });
this.httprequest._dispatcher.ws = this; this.httprequest._dispatcher.ws = this;
this.httprequest._dispatcher.on('connection', function (c) this.httprequest._dispatcher.on('connection', function (c) {
{
this.ws._term = c; this.ws._term = c;
c.pipe(this.ws, { dataTypeSkip: 1 }); c.pipe(this.ws, { dataTypeSkip: 1 });
this.ws.pipe(c, { dataTypeSkip: 1 }); this.ws.pipe(c, { dataTypeSkip: 1 });
}); });
} }
else else {
{
// Legacy Terminal // Legacy Terminal
this.httprequest._term = require('win-terminal').Start(80, 25); this.httprequest._term = require('win-terminal').Start(80, 25);
this.httprequest._term.pipe(this, { dataTypeSkip: 1 }); this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
@ -685,22 +651,18 @@ require('MeshAgent').AddCommandHandler(function (data)
this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); }); this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
} }
} }
else else {
{
var env = { HISTCONTROL: 'ignoreboth' }; var env = { HISTCONTROL: 'ignoreboth' };
if (this.httprequest.xoptions) if (this.httprequest.xoptions) {
{
if (this.httprequest.xoptions.rows) { env.LINES = ('' + this.httprequest.xoptions.rows); } if (this.httprequest.xoptions.rows) { env.LINES = ('' + this.httprequest.xoptions.rows); }
if (this.httprequest.xoptions.cols) { env.COLUMNS = ('' + this.httprequest.xoptions.cols); } if (this.httprequest.xoptions.cols) { env.COLUMNS = ('' + this.httprequest.xoptions.cols); }
} }
var options = { type: childProcess.SpawnTypes.TERM, env: env }; var options = { type: childProcess.SpawnTypes.TERM, env: env };
if (require('fs').existsSync('/bin/bash')) if (require('fs').existsSync('/bin/bash')) {
{
this.httprequest.process = childProcess.execFile('/bin/bash', ['bash'], options); // Start bash this.httprequest.process = childProcess.execFile('/bin/bash', ['bash'], options); // Start bash
} }
else else {
{
this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], options); // Start sh this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], options); // Start sh
} }
@ -715,8 +677,7 @@ require('MeshAgent').AddCommandHandler(function (data)
} }
} }
} }
else if (this.httprequest.protocol == 5) else if (this.httprequest.protocol == 5) {
{
// Process files commands // Process files commands
var cmd = null; var cmd = null;
try { cmd = JSON.parse(data); } catch (e) { }; try { cmd = JSON.parse(data); } catch (e) { };
@ -729,8 +690,7 @@ require('MeshAgent').AddCommandHandler(function (data)
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows 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, ' ')); //console.log(objToString(cmd, 0, ' '));
switch (cmd.action) switch (cmd.action) {
{
case 'ls': case 'ls':
// Send the folder content to the browser // Send the folder content to the browser
var response = getDirectoryInfo(cmd.path); var response = getDirectoryInfo(cmd.path);
@ -746,8 +706,7 @@ require('MeshAgent').AddCommandHandler(function (data)
case 'rm': case 'rm':
{ {
// Delete, possibly recursive delete // Delete, possibly recursive delete
for (var i in cmd.delfiles) for (var i in cmd.delfiles) {
{
try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { } try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
} }
break; break;
@ -782,15 +741,11 @@ require('MeshAgent').AddCommandHandler(function (data)
{ {
// Download a file // Download a file
var sendNextBlock = 0; var sendNextBlock = 0;
if (cmd.sub == 'start') if (cmd.sub == 'start') { // Setup the download
{ // Setup the download if ((cmd.path == null) && (cmd.ask == 'coredump')) { // If we are asking for the coredump file, set the right path.
if ((cmd.path == null) && (cmd.ask == 'coredump')) if (process.platform == 'win32') {
{ // If we are asking for the coredump file, set the right path.
if (process.platform == 'win32')
{
if (fs.existsSync(process.coreDumpLocation)) { cmd.path = process.coreDumpLocation; } if (fs.existsSync(process.coreDumpLocation)) { cmd.path = process.coreDumpLocation; }
} else } else {
{
if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) { cmd.path = process.cwd() + 'core'; } if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) { cmd.path = process.cwd() + 'core'; }
} }
} }
@ -799,13 +754,11 @@ require('MeshAgent').AddCommandHandler(function (data)
this.filedownload = { id: cmd.id, path: cmd.path, ptr: 0 } this.filedownload = { id: cmd.id, path: cmd.path, ptr: 0 }
try { this.filedownload.f = fs.openSync(this.filedownload.path, 'rbN'); } catch (e) { this.write({ action: 'download', sub: 'cancel', id: this.filedownload.id }); delete this.filedownload; } try { this.filedownload.f = fs.openSync(this.filedownload.path, 'rbN'); } catch (e) { this.write({ action: 'download', sub: 'cancel', id: this.filedownload.id }); delete this.filedownload; }
if (this.filedownload) { this.write({ action: 'download', sub: 'start', id: cmd.id }); } if (this.filedownload) { this.write({ action: 'download', sub: 'start', id: cmd.id }); }
} else if ((this.filedownload != null) && (cmd.id == this.filedownload.id)) } else if ((this.filedownload != null) && (cmd.id == this.filedownload.id)) { // Download commands
{ // Download commands
if (cmd.sub == 'startack') { sendNextBlock = ((typeof cmd.ack == 'number') ? cmd.ack : 8); } else if (cmd.sub == 'stop') { delete this.filedownload; } else if (cmd.sub == 'ack') { sendNextBlock = 1; } if (cmd.sub == 'startack') { sendNextBlock = ((typeof cmd.ack == 'number') ? cmd.ack : 8); } else if (cmd.sub == 'stop') { delete this.filedownload; } else if (cmd.sub == 'ack') { sendNextBlock = 1; }
} }
// Send the next download block(s) // Send the next download block(s)
while (sendNextBlock > 0) while (sendNextBlock > 0) {
{
sendNextBlock--; sendNextBlock--;
var buf = Buffer.alloc(16384); var buf = Buffer.alloc(16384);
var len = fs.readSync(this.filedownload.f, buf, 4, 16380, null); var len = fs.readSync(this.filedownload.f, buf, 4, 16380, null);
@ -831,8 +784,7 @@ require('MeshAgent').AddCommandHandler(function (data)
case 'uploaddone': case 'uploaddone':
{ {
// Indicates that an upload is done // Indicates that an upload is done
if (this.httprequest.uploadFile) if (this.httprequest.uploadFile) {
{
fs.closeSync(this.httprequest.uploadFile); fs.closeSync(this.httprequest.uploadFile);
this.write(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file. this.write(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
delete this.httprequest.uploadFile; delete this.httprequest.uploadFile;
@ -844,8 +796,7 @@ require('MeshAgent').AddCommandHandler(function (data)
case 'uploadcancel': case 'uploadcancel':
{ {
// Indicates that an upload is canceled // Indicates that an upload is canceled
if (this.httprequest.uploadFile) if (this.httprequest.uploadFile) {
{
fs.closeSync(this.httprequest.uploadFile); fs.closeSync(this.httprequest.uploadFile);
fs.unlinkSync(this.httprequest.uploadFilePath); fs.unlinkSync(this.httprequest.uploadFilePath);
this.write(Buffer.from(JSON.stringify({ action: 'uploadcancel', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file. this.write(Buffer.from(JSON.stringify({ action: 'uploadcancel', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
@ -857,8 +808,7 @@ require('MeshAgent').AddCommandHandler(function (data)
} }
case 'copy': { case 'copy': {
// Copy a bunch of files from scpath to dspath // Copy a bunch of files from scpath to dspath
for (var i in cmd.names) for (var i in cmd.names) {
{
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]); 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) { } } if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
} }
@ -866,8 +816,7 @@ require('MeshAgent').AddCommandHandler(function (data)
} }
case 'move': { case 'move': {
// Move a bunch of files from scpath to dspath // Move a bunch of files from scpath to dspath
for (var i in cmd.names) for (var i in cmd.names) {
{
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]); 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) { } } if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
} }
@ -931,11 +880,9 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
break; break;
case 'eval': case 'eval':
{ // Eval JavaScript { // Eval JavaScript
if (args['_'].length < 1) if (args['_'].length < 1) {
{
response = 'Proper usage: eval "JavaScript code"'; // Display correct command usage response = 'Proper usage: eval "JavaScript code"'; // Display correct command usage
} else } else {
{
response = JSON.stringify(require('MeshAgent').eval(args['_'][0])); // This can only be run by trusted administrator. response = JSON.stringify(require('MeshAgent').eval(args['_'][0])); // This can only be run by trusted administrator.
} }
break; break;
@ -949,12 +896,10 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
case 'osinfo': { // Return the operating system information case 'osinfo': { // Return the operating system information
var i = 1; var i = 1;
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; } if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
for (var j = 0; j < i; j++) for (var j = 0; j < i; j++) {
{
var pr = require('os').name(); var pr = require('os').name();
pr.sessionid = sessionid; pr.sessionid = sessionid;
pr.then(function (v) pr.then(function (v) {
{
sendConsoleText("OS: " + v + (process.platform == 'win32' ? (require('win-virtual-terminal').supported ? ' [ConPTY: YES]' : ' [ConPTY: NO]') : ''), this.sessionid); sendConsoleText("OS: " + v + (process.platform == 'win32' ? (require('win-virtual-terminal').supported ? ' [ConPTY: YES]' : ' [ConPTY: NO]') : ''), this.sessionid);
}); });
} }