Improvements to plugin support.

This commit is contained in:
Ylian Saint-Hilaire 2019-10-10 11:13:25 -07:00
parent 4b8d0a4937
commit dece20ac93
11 changed files with 15748 additions and 561 deletions

View File

@ -117,6 +117,7 @@
<Compile Include="meshuser.js" /> <Compile Include="meshuser.js" />
<Compile Include="mpsserver.js" /> <Compile Include="mpsserver.js" />
<Compile Include="mqttbroker.js" /> <Compile Include="mqttbroker.js" />
<Compile Include="pluginHandler.js" />
<Compile Include="public\scripts\agent-redir-rtc-0.1.0.js" /> <Compile Include="public\scripts\agent-redir-rtc-0.1.0.js" />
<Compile Include="swarmserver.js" /> <Compile Include="swarmserver.js" />
<Compile Include="multiserver.js" /> <Compile Include="multiserver.js" />

View File

@ -37,12 +37,10 @@ var MESHRIGHT_NOFILES = 1024;
var MESHRIGHT_NOAMT = 2048; var MESHRIGHT_NOAMT = 2048;
var MESHRIGHT_LIMITEDINPUT = 4096; var MESHRIGHT_LIMITEDINPUT = 4096;
function createMeshCore(agent) function createMeshCore(agent) {
{
var obj = {}; var obj = {};
if (process.platform == 'darwin' && !process.versions) if (process.platform == 'darwin' && !process.versions) {
{
// This is an older MacOS Agent, so we'll need to check the service definition so that Auto-Update will function correctly // This is an older MacOS Agent, so we'll need to check the service definition so that Auto-Update will function correctly
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.str = '';
@ -51,21 +49,18 @@ function createMeshCore(agent)
child.stdin.write(" if(c[1]==\"dict\"){ split(a[2], d, \"</dict>\"); if(split(d[1], truval, \"<true/>\")>1) { split(truval[1], kn1, \"<key>\"); split(kn1[2], kn2, \"</key>\"); print kn2[1]; } }"); child.stdin.write(" if(c[1]==\"dict\"){ split(a[2], d, \"</dict>\"); if(split(d[1], truval, \"<true/>\")>1) { split(truval[1], kn1, \"<key>\"); split(kn1[2], kn2, \"</key>\"); print kn2[1]; } }");
child.stdin.write(" else { split(c[1], ka, \"/\"); if(ka[1]==\"true\") {print \"ALWAYS\";} } }'\nexit\n"); child.stdin.write(" else { split(c[1], ka, \"/\"); if(ka[1]==\"true\") {print \"ALWAYS\";} } }'\nexit\n");
child.waitExit(); child.waitExit();
if (child.stdout.str.trim() == 'Crashed') if (child.stdout.str.trim() == 'Crashed') {
{
child = require('child_process').execFile('/bin/sh', ['sh']); child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write("launchctl list | grep 'meshagent' | awk '{ if($3==\"meshagent\"){print $1;}}'\nexit\n"); child.stdin.write("launchctl list | grep 'meshagent' | awk '{ if($3==\"meshagent\"){print $1;}}'\nexit\n");
child.waitExit(); child.waitExit();
if (parseInt(child.stdout.str.trim()) == process.pid) if (parseInt(child.stdout.str.trim()) == process.pid) {
{
// The currently running MeshAgent is us, so we can continue with the update // The currently running MeshAgent is us, so we can continue with the update
var plist = require('fs').readFileSync('/Library/LaunchDaemons/meshagent_osx64_LaunchDaemon.plist').toString(); var plist = require('fs').readFileSync('/Library/LaunchDaemons/meshagent_osx64_LaunchDaemon.plist').toString();
var tokens = plist.split('<key>KeepAlive</key>'); var tokens = plist.split('<key>KeepAlive</key>');
if (tokens[1].split('>')[0].split('<')[1] == 'dict') if (tokens[1].split('>')[0].split('<')[1] == 'dict') {
{
var tmp = tokens[1].split('</dict>'); var tmp = tokens[1].split('</dict>');
tmp.shift(); tmp.shift();
tokens[1] = '\n <true/>' + tmp.join('</dict>'); tokens[1] = '\n <true/>' + tmp.join('</dict>');
@ -125,10 +120,8 @@ function createMeshCore(agent)
if (process.platform != 'win32') { try { require('fs').unlinkSync(process.cwd() + '/DAIPC'); } catch (ee) { } } if (process.platform != 'win32') { try { require('fs').unlinkSync(process.cwd() + '/DAIPC'); } catch (ee) { } }
obj.DAIPC.IPCPATH = process.platform == 'win32' ? ('\\\\.\\pipe\\' + require('_agentNodeId')() + '-DAIPC') : (process.cwd() + '/DAIPC'); obj.DAIPC.IPCPATH = process.platform == 'win32' ? ('\\\\.\\pipe\\' + require('_agentNodeId')() + '-DAIPC') : (process.cwd() + '/DAIPC');
try { obj.DAIPC.listen({ path: obj.DAIPC.IPCPATH }); } catch (e) { } try { obj.DAIPC.listen({ path: obj.DAIPC.IPCPATH }); } catch (e) { }
obj.DAIPC.on('connection', function (c) obj.DAIPC.on('connection', function (c) {
{ c._send = function (j) {
c._send = function (j)
{
var data = JSON.stringify(j); var data = JSON.stringify(j);
var packet = Buffer.alloc(data.length + 4); var packet = Buffer.alloc(data.length + 4);
packet.writeUInt32LE(data.length + 4, 0); packet.writeUInt32LE(data.length + 4, 0);
@ -138,32 +131,26 @@ function createMeshCore(agent)
this._daipc = c; this._daipc = c;
c.parent = this; c.parent = this;
c.on('end', function () { console.log('Connection Closed'); this.parent._daipc = null; }); c.on('end', function () { console.log('Connection Closed'); this.parent._daipc = null; });
c.on('data', function (chunk) c.on('data', function (chunk) {
{
if (chunk.length < 4) { this.unshift(chunk); return; } if (chunk.length < 4) { this.unshift(chunk); return; }
var len = chunk.readUInt32LE(0); var len = chunk.readUInt32LE(0);
if (len > 8192) { this.parent._daipc = null; this.end(); return; } if (len > 8192) { this.parent._daipc = null; this.end(); return; }
if (chunk.length < len) { this.unshift(chunk); return; } if (chunk.length < len) { this.unshift(chunk); return; }
var data = chunk.slice(4, len); var data = chunk.slice(4, len);
try try {
{
data = JSON.parse(data.toString()); data = JSON.parse(data.toString());
} }
catch(de) catch (de) {
{
this.parent._daipc = null; this.end(); return; this.parent._daipc = null; this.end(); return;
} }
if (!data.cmd) { this.parent._daipc = null; this.end(); return; } if (!data.cmd) { this.parent._daipc = null; this.end(); return; }
try try {
{ switch (data.cmd) {
switch(data.cmd)
{
case 'query': case 'query':
switch(data.value) switch (data.value) {
{
case 'connection': case 'connection':
data.result = require('MeshAgent').ConnectedServer; data.result = require('MeshAgent').ConnectedServer;
this._send(data); this._send(data);
@ -176,32 +163,26 @@ function createMeshCore(agent)
return; return;
} }
} }
catch(xe) catch (xe) {
{
this.parent._daipc = null; this.end(); return; this.parent._daipc = null; this.end(); return;
} }
}); });
}); });
function diagnosticAgent_uninstall() function diagnosticAgent_uninstall() {
{
require('service-manager').manager.uninstallService('meshagentDiagnostic'); require('service-manager').manager.uninstallService('meshagentDiagnostic');
require('task-scheduler').delete('meshagentDiagnostic/periodicStart'); require('task-scheduler').delete('meshagentDiagnostic/periodicStart');
}; };
function diagnosticAgent_installCheck(install) function diagnosticAgent_installCheck(install) {
{ try {
try
{
var diag = require('service-manager').manager.getService('meshagentDiagnostic'); var diag = require('service-manager').manager.getService('meshagentDiagnostic');
return (diag); return (diag);
} }
catch (e) catch (e) {
{
} }
if (!install) { return (null); } if (!install) { return (null); }
var svc = null; var svc = null;
try try {
{
require('service-manager').manager.installService( require('service-manager').manager.installService(
{ {
name: 'meshagentDiagnostic', name: 'meshagentDiagnostic',
@ -213,8 +194,7 @@ function createMeshCore(agent)
}); });
svc = require('service-manager').manager.getService('meshagentDiagnostic'); svc = require('service-manager').manager.getService('meshagentDiagnostic');
} }
catch (e) catch (e) {
{
return (null); return (null);
} }
var proxyConfig = require('global-tunnel').proxyConfig; var proxyConfig = require('global-tunnel').proxyConfig;
@ -227,12 +207,10 @@ function createMeshCore(agent)
ddb.Put('MeshServer', require('MeshAgent').ServerInfo.ServerUri); ddb.Put('MeshServer', require('MeshAgent').ServerInfo.ServerUri);
if (cert.root.pfx) { ddb.Put('SelfNodeCert', cert.root.pfx); } if (cert.root.pfx) { ddb.Put('SelfNodeCert', cert.root.pfx); }
if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); } if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); }
if (proxyConfig) if (proxyConfig) {
{
ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port); ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port);
} }
else else {
{
ddb.Put('ignoreProxyFile', '1'); ddb.Put('ignoreProxyFile', '1');
} }
@ -831,6 +809,18 @@ function createMeshCore(agent)
} }
case 'ping': { mesh.SendCommand('{"action":"pong"}'); break; } case 'ping': { mesh.SendCommand('{"action":"pong"}'); break; }
case 'pong': { break; } case 'pong': { break; }
case 'plugin': {
if (typeof data.pluginaction == 'string') {
try {
MeshServerLog('Plugin called', data);
// Not yet implemented
// require(data.plugin.name).serveraction(data);
} catch (e) {
MeshServerLog('Error calling plugin', data);
}
}
break;
}
default: default:
// Unknown action, ignore it. // Unknown action, ignore it.
break; break;
@ -1069,17 +1059,14 @@ function createMeshCore(agent)
return; return;
} }
this.end = function () this.end = function () {
{ if (process.platform == "win32") {
if (process.platform == "win32")
{
// Unpipe the web socket // Unpipe the web socket
this.unpipe(this.httprequest._term); this.unpipe(this.httprequest._term);
if (this.httprequest._term) { this.httprequest._term.unpipe(this); } if (this.httprequest._term) { this.httprequest._term.unpipe(this); }
// Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends). // Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends).
if (this.rtcchannel) if (this.rtcchannel) {
{
this.rtcchannel.unpipe(this.httprequest._term); this.rtcchannel.unpipe(this.httprequest._term);
if (this.httprequest._term) { this.httprequest._term.unpipe(this.rtcchannel); } if (this.httprequest._term) { this.httprequest._term.unpipe(this.rtcchannel); }
} }
@ -1087,27 +1074,21 @@ function createMeshCore(agent)
// Clean up // Clean up
if (this.httprequest._term) { this.httprequest._term.end(); } if (this.httprequest._term) { this.httprequest._term.end(); }
this.httprequest._term = null; this.httprequest._term = null;
} else } else {
{
// TODO!! // TODO!!
} }
}; };
// Remote terminal using native pipes // Remote terminal using native pipes
if (process.platform == "win32") if (process.platform == "win32") {
{ try {
try if ((this.httprequest.protocol == 6) && (require('win-terminal').PowerShellCapable() == true)) {
{
if ((this.httprequest.protocol == 6) && (require('win-terminal').PowerShellCapable() == true))
{
this.httprequest._term = require('win-terminal').StartPowerShell(80, 25); this.httprequest._term = require('win-terminal').StartPowerShell(80, 25);
} else } else {
{
this.httprequest._term = require('win-terminal').Start(80, 25); this.httprequest._term = require('win-terminal').Start(80, 25);
} }
} }
catch(e) catch (e) {
{
MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest); MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() })); this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() }));
this.end(); this.end();
@ -1116,14 +1097,11 @@ function createMeshCore(agent)
this.httprequest._term.pipe(this, { dataTypeSkip: 1 }); this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false }); this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
this.prependListener('end', function () { this.httprequest._term.end(function () { console.log('Terminal was closed'); }); }); this.prependListener('end', function () { this.httprequest._term.end(function () { console.log('Terminal was closed'); }); });
} else } else {
{ if (fs.existsSync("/bin/bash")) {
if (fs.existsSync("/bin/bash"))
{
this.httprequest.process = childProcess.execFile("/bin/bash", ["bash", "-i"], { type: childProcess.SpawnTypes.TERM }); this.httprequest.process = childProcess.execFile("/bin/bash", ["bash", "-i"], { type: childProcess.SpawnTypes.TERM });
if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); } if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); }
} else } else {
{
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM }); this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); } if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); }
} }
@ -1176,8 +1154,7 @@ function createMeshCore(agent)
this.removeAllListeners('data'); this.removeAllListeners('data');
this.on('data', onTunnelControlData); this.on('data', onTunnelControlData);
//this.write('MeshCore Terminal Hello'); //this.write('MeshCore Terminal Hello');
} else if (this.httprequest.protocol == 2) } else if (this.httprequest.protocol == 2) {
{
// Check user access rights for desktop // Check user access rights for desktop
if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) { if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) {
// Disengage this tunnel, user does not have the rights to do this!! // Disengage this tunnel, user does not have the rights to do this!!
@ -1225,8 +1202,7 @@ function createMeshCore(agent)
} }
// Perform notification if needed. Toast messages may not be supported on all platforms. // Perform notification if needed. Toast messages may not be supported on all platforms.
if (this.httprequest.consent && (this.httprequest.consent & 8)) if (this.httprequest.consent && (this.httprequest.consent & 8)) {
{
// User Consent Prompt is required // User Consent Prompt is required
// Send a console message back using the console channel, "\n" is supported. // Send a console message back using the console channel, "\n" is supported.
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' })); this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' }));
@ -1235,8 +1211,7 @@ function createMeshCore(agent)
this.pause(); this.pause();
pr.then( pr.then(
function () function () {
{
// Success // Success
MeshServerLog('Starting remote desktop after local user accepted (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest); MeshServerLog('Starting remote desktop after local user accepted (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest);
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null })); this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null }));
@ -1247,15 +1222,13 @@ function createMeshCore(agent)
this.ws.httprequest.desktop.kvm.pipe(this.ws, { dataTypeSkip: 1 }); this.ws.httprequest.desktop.kvm.pipe(this.ws, { dataTypeSkip: 1 });
this.ws.resume(); this.ws.resume();
}, },
function (e) function (e) {
{
// User Consent Denied/Failed // User Consent Denied/Failed
MeshServerLog('Failed to start remote desktop after local user rejected (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest); MeshServerLog('Failed to start remote desktop after local user rejected (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest);
this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() })); this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() }));
}); });
} }
else else {
{
// User Consent Prompt is not required // User Consent Prompt is not required
if (this.httprequest.consent && (this.httprequest.consent & 1)) { if (this.httprequest.consent && (this.httprequest.consent & 1)) {
// User Notifications is required // User Notifications is required
@ -1283,8 +1256,7 @@ function createMeshCore(agent)
} }
// Perform notification if needed. Toast messages may not be supported on all platforms. // Perform notification if needed. Toast messages may not be supported on all platforms.
if (this.httprequest.consent && (this.httprequest.consent & 32)) if (this.httprequest.consent && (this.httprequest.consent & 32)) {
{
// User Consent Prompt is required // User Consent Prompt is required
// Send a console message back using the console channel, "\n" is supported. // Send a console message back using the console channel, "\n" is supported.
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' })); this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' }));
@ -1479,6 +1451,23 @@ function createMeshCore(agent)
// Unknown action, ignore it. // Unknown action, ignore it.
break; break;
} }
} else if (this.httprequest.protocol == 7) { // plugin data exchange
var cmd = null;
try { cmd = JSON.parse(data); } catch (e) { };
if (cmd == null) { return; }
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { onTunnelControlData(cmd, this); return; } // If this is control data, handle it now.
if (cmd.action == undefined) return;
switch (cmd.action) {
case 'plugin': {
try { require(cmd.plugin).consoleaction(cmd, null, null, this); } catch (e) { throw e; }
break;
}
default: {
// probably shouldn't happen, but just in case this feature is expanded
}
}
} }
//sendConsoleText("Got tunnel #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid); //sendConsoleText("Got tunnel #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid);
} }
@ -1553,12 +1542,10 @@ function createMeshCore(agent)
} else if (obj.type == 'webrtc0') { // Browser indicates we can start WebRTC switch-over. } else if (obj.type == 'webrtc0') { // Browser indicates we can start WebRTC switch-over.
if (ws.httprequest.protocol == 1) { // Terminal if (ws.httprequest.protocol == 1) { // Terminal
// This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket // This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket
if (process.platform == 'win32') if (process.platform == 'win32') {
{
ws.httprequest._term.unpipe(ws); ws.httprequest._term.unpipe(ws);
} }
else else {
{
ws.httprequest.process.stdout.unpipe(ws); ws.httprequest.process.stdout.unpipe(ws);
ws.httprequest.process.stderr.unpipe(ws); ws.httprequest.process.stderr.unpipe(ws);
} }
@ -1575,13 +1562,11 @@ function createMeshCore(agent)
} else if (obj.type == 'webrtc1') { } else if (obj.type == 'webrtc1') {
if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
// Switch the user input from websocket to webrtc at this point. // Switch the user input from websocket to webrtc at this point.
if (process.platform == 'win32') if (process.platform == 'win32') {
{
ws.unpipe(ws.httprequest._term); ws.unpipe(ws.httprequest._term);
ws.rtcchannel.pipe(ws.httprequest._term, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text. ws.rtcchannel.pipe(ws.httprequest._term, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
} }
else else {
{
ws.unpipe(ws.httprequest.process.stdin); ws.unpipe(ws.httprequest.process.stdin);
ws.rtcchannel.pipe(ws.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text. ws.rtcchannel.pipe(ws.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
} }
@ -1596,12 +1581,10 @@ function createMeshCore(agent)
} else if (obj.type == 'webrtc2') { } else if (obj.type == 'webrtc2') {
// Other side received websocket end of data marker, start sending data on WebRTC channel // Other side received websocket end of data marker, start sending data on WebRTC channel
if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
if (process.platform == 'win32') if (process.platform == 'win32') {
{
ws.httprequest._term.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. ws.httprequest._term.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
} }
else else {
{
ws.httprequest.process.stdout.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. ws.httprequest.process.stdout.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
ws.httprequest.process.stderr.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. ws.httprequest.process.stderr.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
} }
@ -1684,7 +1667,7 @@ function createMeshCore(agent)
var response = null; var response = null;
switch (cmd) { switch (cmd) {
case 'help': { // Displays available commands case 'help': { // Displays available commands
var fin = '', f = '', availcommands = 'help,info,osinfo,args,print,type,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt'; var fin = '', f = '', availcommands = 'help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt';
availcommands = availcommands.split(',').sort(); availcommands = availcommands.split(',').sort();
while (availcommands.length > 0) { while (availcommands.length > 0) {
if (f.length > 100) { fin += (f + ',\r\n'); f = ''; } if (f.length > 100) { fin += (f + ',\r\n'); f = ''; }
@ -1836,14 +1819,11 @@ function createMeshCore(agent)
break; break;
} }
case 'dump': case 'dump':
if (args['_'].length < 1) if (args['_'].length < 1) {
{
response = 'Proper usage: dump [on/off/status]'; // Display correct command usage response = 'Proper usage: dump [on/off/status]'; // Display correct command usage
} }
else else {
{ switch (args['_'][0].toLowerCase()) {
switch(args['_'][0].toLowerCase())
{
case 'on': case 'on':
process.coreDumpLocation = process.platform == 'win32' ? process.execPath.replace('.exe', '.dmp') : (process.execPath + '.dmp'); process.coreDumpLocation = process.platform == 'win32' ? process.execPath.replace('.exe', '.dmp') : (process.execPath + '.dmp');
response = 'enabled'; response = 'enabled';
@ -1853,12 +1833,10 @@ function createMeshCore(agent)
response = 'disabled'; response = 'disabled';
break; break;
case 'status': case 'status':
if (process.coreDumpLocation) if (process.coreDumpLocation) {
{
response = 'Core Dump: [ENABLED' + (require('fs').existsSync(process.coreDumpLocation) ? (', (DMP file exists)]') : (']')); response = 'Core Dump: [ENABLED' + (require('fs').existsSync(process.coreDumpLocation) ? (', (DMP file exists)]') : (']'));
} }
else else {
{
response = 'Core Dump: [DISABLED]'; response = 'Core Dump: [DISABLED]';
} }
break; break;
@ -1878,18 +1856,14 @@ function createMeshCore(agent)
} }
case 'uninstallagent': case 'uninstallagent':
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
if (!require('service-manager').manager.getService(agentName).isMe()) if (!require('service-manager').manager.getService(agentName).isMe()) {
{
response = 'Uininstall failed, this instance is not the service instance'; response = 'Uininstall failed, this instance is not the service instance';
} }
else else {
{ try {
try
{
diagnosticAgent_uninstall(); diagnosticAgent_uninstall();
} }
catch(x) catch (x) {
{
} }
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();"; var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true }); this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
@ -2256,40 +2230,31 @@ function createMeshCore(agent)
} }
case 'diagnostic': case 'diagnostic':
{ {
if (!mesh.DAIPC.listening) if (!mesh.DAIPC.listening) {
{
response = 'Unable to bind to Diagnostic IPC, most likely because the path (' + process.cwd() + ') is not on a local file system'; response = 'Unable to bind to Diagnostic IPC, most likely because the path (' + process.cwd() + ') is not on a local file system';
break; break;
} }
var diag = diagnosticAgent_installCheck(); var diag = diagnosticAgent_installCheck();
if (diag) if (diag) {
{ if (args['_'].length == 1 && args['_'][0] == 'uninstall') {
if (args['_'].length == 1 && args['_'][0] == 'uninstall')
{
diagnosticAgent_uninstall(); diagnosticAgent_uninstall();
response = 'Diagnostic Agent uninstalled'; response = 'Diagnostic Agent uninstalled';
} }
else else {
{
response = 'Diagnostic Agent installed at: ' + diag.appLocation(); response = 'Diagnostic Agent installed at: ' + diag.appLocation();
} }
} }
else else {
{ if (args['_'].length == 1 && args['_'][0] == 'install') {
if (args['_'].length == 1 && args['_'][0] == 'install')
{
diag = diagnosticAgent_installCheck(true); diag = diagnosticAgent_installCheck(true);
if (diag) if (diag) {
{
response = 'Diagnostic agent was installed at: ' + diag.appLocation(); response = 'Diagnostic agent was installed at: ' + diag.appLocation();
} }
else else {
{
response = 'Diagnostic agent installation failed'; response = 'Diagnostic agent installation failed';
} }
} }
else else {
{
response = 'Diagnostic Agent Not installed. To install: diagnostic install'; response = 'Diagnostic Agent Not installed. To install: diagnostic install';
} }
} }
@ -2339,6 +2304,21 @@ function createMeshCore(agent)
} }
break; break;
} }
case 'plugin': {
if (typeof args['_'][0] == 'string') {
try {
// Pass off the action to the plugin
// for plugin creators, you'll want to have a plugindir/modules_meshcore/plugin.js
// to control the output / actions here.
response = require(args['_'][0]).consoleaction(args, rights, sessionid, mesh);
} catch (e) {
response = 'There was an error in the plugin (' + e + ')';
}
} else {
response = 'Proper usage: plugin [pluginName] [args].';
}
break;
}
default: { // This is an unknown command, return an error message default: { // This is an unknown command, return an error message
response = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.'; response = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
break; break;
@ -2451,6 +2431,8 @@ function createMeshCore(agent)
//if (process.platform == 'win32') { try { pr = require('win-info').pendingReboot(); } catch (ex) { pr = null; } } // Pending reboot //if (process.platform == 'win32') { try { pr = require('win-info').pendingReboot(); } catch (ex) { pr = null; } } // Pending reboot
if ((meshCoreObj.av == null) || (JSON.stringify(meshCoreObj.av) != JSON.stringify(av))) { meshCoreObj.av = av; mesh.SendCommand(meshCoreObj); } if ((meshCoreObj.av == null) || (JSON.stringify(meshCoreObj.av) != JSON.stringify(av))) { meshCoreObj.av = av; mesh.SendCommand(meshCoreObj); }
} }
// TODO: add plugin hook here
} }

207
agents/meshcore.min.js vendored
View File

@ -37,12 +37,10 @@ var MESHRIGHT_NOFILES = 1024;
var MESHRIGHT_NOAMT = 2048; var MESHRIGHT_NOAMT = 2048;
var MESHRIGHT_LIMITEDINPUT = 4096; var MESHRIGHT_LIMITEDINPUT = 4096;
function createMeshCore(agent) function createMeshCore(agent) {
{
var obj = {}; var obj = {};
if (process.platform == 'darwin' && !process.versions) if (process.platform == 'darwin' && !process.versions) {
{
// This is an older MacOS Agent, so we'll need to check the service definition so that Auto-Update will function correctly // This is an older MacOS Agent, so we'll need to check the service definition so that Auto-Update will function correctly
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.str = '';
@ -51,21 +49,18 @@ function createMeshCore(agent)
child.stdin.write(" if(c[1]==\"dict\"){ split(a[2], d, \"</dict>\"); if(split(d[1], truval, \"<true/>\")>1) { split(truval[1], kn1, \"<key>\"); split(kn1[2], kn2, \"</key>\"); print kn2[1]; } }"); child.stdin.write(" if(c[1]==\"dict\"){ split(a[2], d, \"</dict>\"); if(split(d[1], truval, \"<true/>\")>1) { split(truval[1], kn1, \"<key>\"); split(kn1[2], kn2, \"</key>\"); print kn2[1]; } }");
child.stdin.write(" else { split(c[1], ka, \"/\"); if(ka[1]==\"true\") {print \"ALWAYS\";} } }'\nexit\n"); child.stdin.write(" else { split(c[1], ka, \"/\"); if(ka[1]==\"true\") {print \"ALWAYS\";} } }'\nexit\n");
child.waitExit(); child.waitExit();
if (child.stdout.str.trim() == 'Crashed') if (child.stdout.str.trim() == 'Crashed') {
{
child = require('child_process').execFile('/bin/sh', ['sh']); child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write("launchctl list | grep 'meshagent' | awk '{ if($3==\"meshagent\"){print $1;}}'\nexit\n"); child.stdin.write("launchctl list | grep 'meshagent' | awk '{ if($3==\"meshagent\"){print $1;}}'\nexit\n");
child.waitExit(); child.waitExit();
if (parseInt(child.stdout.str.trim()) == process.pid) if (parseInt(child.stdout.str.trim()) == process.pid) {
{
// The currently running MeshAgent is us, so we can continue with the update // The currently running MeshAgent is us, so we can continue with the update
var plist = require('fs').readFileSync('/Library/LaunchDaemons/meshagent_osx64_LaunchDaemon.plist').toString(); var plist = require('fs').readFileSync('/Library/LaunchDaemons/meshagent_osx64_LaunchDaemon.plist').toString();
var tokens = plist.split('<key>KeepAlive</key>'); var tokens = plist.split('<key>KeepAlive</key>');
if (tokens[1].split('>')[0].split('<')[1] == 'dict') if (tokens[1].split('>')[0].split('<')[1] == 'dict') {
{
var tmp = tokens[1].split('</dict>'); var tmp = tokens[1].split('</dict>');
tmp.shift(); tmp.shift();
tokens[1] = '\n <true/>' + tmp.join('</dict>'); tokens[1] = '\n <true/>' + tmp.join('</dict>');
@ -125,10 +120,8 @@ function createMeshCore(agent)
if (process.platform != 'win32') { try { require('fs').unlinkSync(process.cwd() + '/DAIPC'); } catch (ee) { } } if (process.platform != 'win32') { try { require('fs').unlinkSync(process.cwd() + '/DAIPC'); } catch (ee) { } }
obj.DAIPC.IPCPATH = process.platform == 'win32' ? ('\\\\.\\pipe\\' + require('_agentNodeId')() + '-DAIPC') : (process.cwd() + '/DAIPC'); obj.DAIPC.IPCPATH = process.platform == 'win32' ? ('\\\\.\\pipe\\' + require('_agentNodeId')() + '-DAIPC') : (process.cwd() + '/DAIPC');
try { obj.DAIPC.listen({ path: obj.DAIPC.IPCPATH }); } catch (e) { } try { obj.DAIPC.listen({ path: obj.DAIPC.IPCPATH }); } catch (e) { }
obj.DAIPC.on('connection', function (c) obj.DAIPC.on('connection', function (c) {
{ c._send = function (j) {
c._send = function (j)
{
var data = JSON.stringify(j); var data = JSON.stringify(j);
var packet = Buffer.alloc(data.length + 4); var packet = Buffer.alloc(data.length + 4);
packet.writeUInt32LE(data.length + 4, 0); packet.writeUInt32LE(data.length + 4, 0);
@ -138,32 +131,26 @@ function createMeshCore(agent)
this._daipc = c; this._daipc = c;
c.parent = this; c.parent = this;
c.on('end', function () { console.log('Connection Closed'); this.parent._daipc = null; }); c.on('end', function () { console.log('Connection Closed'); this.parent._daipc = null; });
c.on('data', function (chunk) c.on('data', function (chunk) {
{
if (chunk.length < 4) { this.unshift(chunk); return; } if (chunk.length < 4) { this.unshift(chunk); return; }
var len = chunk.readUInt32LE(0); var len = chunk.readUInt32LE(0);
if (len > 8192) { this.parent._daipc = null; this.end(); return; } if (len > 8192) { this.parent._daipc = null; this.end(); return; }
if (chunk.length < len) { this.unshift(chunk); return; } if (chunk.length < len) { this.unshift(chunk); return; }
var data = chunk.slice(4, len); var data = chunk.slice(4, len);
try try {
{
data = JSON.parse(data.toString()); data = JSON.parse(data.toString());
} }
catch(de) catch (de) {
{
this.parent._daipc = null; this.end(); return; this.parent._daipc = null; this.end(); return;
} }
if (!data.cmd) { this.parent._daipc = null; this.end(); return; } if (!data.cmd) { this.parent._daipc = null; this.end(); return; }
try try {
{ switch (data.cmd) {
switch(data.cmd)
{
case 'query': case 'query':
switch(data.value) switch (data.value) {
{
case 'connection': case 'connection':
data.result = require('MeshAgent').ConnectedServer; data.result = require('MeshAgent').ConnectedServer;
this._send(data); this._send(data);
@ -176,32 +163,26 @@ function createMeshCore(agent)
return; return;
} }
} }
catch(xe) catch (xe) {
{
this.parent._daipc = null; this.end(); return; this.parent._daipc = null; this.end(); return;
} }
}); });
}); });
function diagnosticAgent_uninstall() function diagnosticAgent_uninstall() {
{
require('service-manager').manager.uninstallService('meshagentDiagnostic'); require('service-manager').manager.uninstallService('meshagentDiagnostic');
require('task-scheduler').delete('meshagentDiagnostic/periodicStart'); require('task-scheduler').delete('meshagentDiagnostic/periodicStart');
}; };
function diagnosticAgent_installCheck(install) function diagnosticAgent_installCheck(install) {
{ try {
try
{
var diag = require('service-manager').manager.getService('meshagentDiagnostic'); var diag = require('service-manager').manager.getService('meshagentDiagnostic');
return (diag); return (diag);
} }
catch (e) catch (e) {
{
} }
if (!install) { return (null); } if (!install) { return (null); }
var svc = null; var svc = null;
try try {
{
require('service-manager').manager.installService( require('service-manager').manager.installService(
{ {
name: 'meshagentDiagnostic', name: 'meshagentDiagnostic',
@ -213,8 +194,7 @@ function createMeshCore(agent)
}); });
svc = require('service-manager').manager.getService('meshagentDiagnostic'); svc = require('service-manager').manager.getService('meshagentDiagnostic');
} }
catch (e) catch (e) {
{
return (null); return (null);
} }
var proxyConfig = require('global-tunnel').proxyConfig; var proxyConfig = require('global-tunnel').proxyConfig;
@ -227,12 +207,10 @@ function createMeshCore(agent)
ddb.Put('MeshServer', require('MeshAgent').ServerInfo.ServerUri); ddb.Put('MeshServer', require('MeshAgent').ServerInfo.ServerUri);
if (cert.root.pfx) { ddb.Put('SelfNodeCert', cert.root.pfx); } if (cert.root.pfx) { ddb.Put('SelfNodeCert', cert.root.pfx); }
if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); } if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); }
if (proxyConfig) if (proxyConfig) {
{
ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port); ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port);
} }
else else {
{
ddb.Put('ignoreProxyFile', '1'); ddb.Put('ignoreProxyFile', '1');
} }
@ -834,10 +812,9 @@ function createMeshCore(agent)
case 'plugin': { case 'plugin': {
if (typeof data.pluginaction == 'string') { if (typeof data.pluginaction == 'string') {
try { try {
MeshServerLog('Plugin called', data); MeshServerLog('Plugin called', data);
/* Not yet implmented // Not yet implemented
require(data.plugin.name).serveraction(data);*/ // require(data.plugin.name).serveraction(data);
} catch (e) { } catch (e) {
MeshServerLog('Error calling plugin', data); MeshServerLog('Error calling plugin', data);
} }
@ -1082,17 +1059,14 @@ function createMeshCore(agent)
return; return;
} }
this.end = function () this.end = function () {
{ if (process.platform == "win32") {
if (process.platform == "win32")
{
// Unpipe the web socket // Unpipe the web socket
this.unpipe(this.httprequest._term); this.unpipe(this.httprequest._term);
if (this.httprequest._term) { this.httprequest._term.unpipe(this); } if (this.httprequest._term) { this.httprequest._term.unpipe(this); }
// Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends). // Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends).
if (this.rtcchannel) if (this.rtcchannel) {
{
this.rtcchannel.unpipe(this.httprequest._term); this.rtcchannel.unpipe(this.httprequest._term);
if (this.httprequest._term) { this.httprequest._term.unpipe(this.rtcchannel); } if (this.httprequest._term) { this.httprequest._term.unpipe(this.rtcchannel); }
} }
@ -1100,27 +1074,21 @@ function createMeshCore(agent)
// Clean up // Clean up
if (this.httprequest._term) { this.httprequest._term.end(); } if (this.httprequest._term) { this.httprequest._term.end(); }
this.httprequest._term = null; this.httprequest._term = null;
} else } else {
{
// TODO!! // TODO!!
} }
}; };
// Remote terminal using native pipes // Remote terminal using native pipes
if (process.platform == "win32") if (process.platform == "win32") {
{ try {
try if ((this.httprequest.protocol == 6) && (require('win-terminal').PowerShellCapable() == true)) {
{
if ((this.httprequest.protocol == 6) && (require('win-terminal').PowerShellCapable() == true))
{
this.httprequest._term = require('win-terminal').StartPowerShell(80, 25); this.httprequest._term = require('win-terminal').StartPowerShell(80, 25);
} else } else {
{
this.httprequest._term = require('win-terminal').Start(80, 25); this.httprequest._term = require('win-terminal').Start(80, 25);
} }
} }
catch(e) catch (e) {
{
MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest); MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() })); this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() }));
this.end(); this.end();
@ -1129,14 +1097,11 @@ function createMeshCore(agent)
this.httprequest._term.pipe(this, { dataTypeSkip: 1 }); this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false }); this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
this.prependListener('end', function () { this.httprequest._term.end(function () { console.log('Terminal was closed'); }); }); this.prependListener('end', function () { this.httprequest._term.end(function () { console.log('Terminal was closed'); }); });
} else } else {
{ if (fs.existsSync("/bin/bash")) {
if (fs.existsSync("/bin/bash"))
{
this.httprequest.process = childProcess.execFile("/bin/bash", ["bash", "-i"], { type: childProcess.SpawnTypes.TERM }); this.httprequest.process = childProcess.execFile("/bin/bash", ["bash", "-i"], { type: childProcess.SpawnTypes.TERM });
if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); } if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); }
} else } else {
{
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM }); this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); } if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); }
} }
@ -1189,8 +1154,7 @@ function createMeshCore(agent)
this.removeAllListeners('data'); this.removeAllListeners('data');
this.on('data', onTunnelControlData); this.on('data', onTunnelControlData);
//this.write('MeshCore Terminal Hello'); //this.write('MeshCore Terminal Hello');
} else if (this.httprequest.protocol == 2) } else if (this.httprequest.protocol == 2) {
{
// Check user access rights for desktop // Check user access rights for desktop
if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) { if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) {
// Disengage this tunnel, user does not have the rights to do this!! // Disengage this tunnel, user does not have the rights to do this!!
@ -1238,8 +1202,7 @@ function createMeshCore(agent)
} }
// Perform notification if needed. Toast messages may not be supported on all platforms. // Perform notification if needed. Toast messages may not be supported on all platforms.
if (this.httprequest.consent && (this.httprequest.consent & 8)) if (this.httprequest.consent && (this.httprequest.consent & 8)) {
{
// User Consent Prompt is required // User Consent Prompt is required
// Send a console message back using the console channel, "\n" is supported. // Send a console message back using the console channel, "\n" is supported.
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' })); this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' }));
@ -1248,8 +1211,7 @@ function createMeshCore(agent)
this.pause(); this.pause();
pr.then( pr.then(
function () function () {
{
// Success // Success
MeshServerLog('Starting remote desktop after local user accepted (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest); MeshServerLog('Starting remote desktop after local user accepted (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest);
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null })); this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null }));
@ -1260,15 +1222,13 @@ function createMeshCore(agent)
this.ws.httprequest.desktop.kvm.pipe(this.ws, { dataTypeSkip: 1 }); this.ws.httprequest.desktop.kvm.pipe(this.ws, { dataTypeSkip: 1 });
this.ws.resume(); this.ws.resume();
}, },
function (e) function (e) {
{
// User Consent Denied/Failed // User Consent Denied/Failed
MeshServerLog('Failed to start remote desktop after local user rejected (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest); MeshServerLog('Failed to start remote desktop after local user rejected (' + this.ws.httprequest.remoteaddr + ')', this.ws.httprequest);
this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() })); this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString() }));
}); });
} }
else else {
{
// User Consent Prompt is not required // User Consent Prompt is not required
if (this.httprequest.consent && (this.httprequest.consent & 1)) { if (this.httprequest.consent && (this.httprequest.consent & 1)) {
// User Notifications is required // User Notifications is required
@ -1296,8 +1256,7 @@ function createMeshCore(agent)
} }
// Perform notification if needed. Toast messages may not be supported on all platforms. // Perform notification if needed. Toast messages may not be supported on all platforms.
if (this.httprequest.consent && (this.httprequest.consent & 32)) if (this.httprequest.consent && (this.httprequest.consent & 32)) {
{
// User Consent Prompt is required // User Consent Prompt is required
// Send a console message back using the console channel, "\n" is supported. // Send a console message back using the console channel, "\n" is supported.
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' })); this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'Waiting for user to grant access...' }));
@ -1497,14 +1456,11 @@ function createMeshCore(agent)
try { cmd = JSON.parse(data); } catch (e) { }; try { cmd = JSON.parse(data); } catch (e) { };
if (cmd == null) { return; } if (cmd == null) { return; }
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { onTunnelControlData(cmd, this); return; } // If this is control data, handle it now. if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { onTunnelControlData(cmd, this); return; } // If this is control data, handle it now.
if (cmd.action == undefined) { return; } if (cmd.action == undefined) return;
switch (cmd.action) { switch (cmd.action) {
case 'plugin': { case 'plugin': {
try { try { require(cmd.plugin).consoleaction(cmd, null, null, this); } catch (e) { throw e; }
require(cmd.plugin).consoleaction(cmd, null, null, this);
} catch (e) { throw e; }
break; break;
} }
default: { default: {
@ -1586,12 +1542,10 @@ function createMeshCore(agent)
} else if (obj.type == 'webrtc0') { // Browser indicates we can start WebRTC switch-over. } else if (obj.type == 'webrtc0') { // Browser indicates we can start WebRTC switch-over.
if (ws.httprequest.protocol == 1) { // Terminal if (ws.httprequest.protocol == 1) { // Terminal
// This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket // This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket
if (process.platform == 'win32') if (process.platform == 'win32') {
{
ws.httprequest._term.unpipe(ws); ws.httprequest._term.unpipe(ws);
} }
else else {
{
ws.httprequest.process.stdout.unpipe(ws); ws.httprequest.process.stdout.unpipe(ws);
ws.httprequest.process.stderr.unpipe(ws); ws.httprequest.process.stderr.unpipe(ws);
} }
@ -1608,13 +1562,11 @@ function createMeshCore(agent)
} else if (obj.type == 'webrtc1') { } else if (obj.type == 'webrtc1') {
if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
// Switch the user input from websocket to webrtc at this point. // Switch the user input from websocket to webrtc at this point.
if (process.platform == 'win32') if (process.platform == 'win32') {
{
ws.unpipe(ws.httprequest._term); ws.unpipe(ws.httprequest._term);
ws.rtcchannel.pipe(ws.httprequest._term, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text. ws.rtcchannel.pipe(ws.httprequest._term, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
} }
else else {
{
ws.unpipe(ws.httprequest.process.stdin); ws.unpipe(ws.httprequest.process.stdin);
ws.rtcchannel.pipe(ws.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text. ws.rtcchannel.pipe(ws.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
} }
@ -1629,12 +1581,10 @@ function createMeshCore(agent)
} else if (obj.type == 'webrtc2') { } else if (obj.type == 'webrtc2') {
// Other side received websocket end of data marker, start sending data on WebRTC channel // Other side received websocket end of data marker, start sending data on WebRTC channel
if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
if (process.platform == 'win32') if (process.platform == 'win32') {
{
ws.httprequest._term.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. ws.httprequest._term.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
} }
else else {
{
ws.httprequest.process.stdout.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. ws.httprequest.process.stdout.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
ws.httprequest.process.stderr.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. ws.httprequest.process.stderr.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
} }
@ -1869,14 +1819,11 @@ function createMeshCore(agent)
break; break;
} }
case 'dump': case 'dump':
if (args['_'].length < 1) if (args['_'].length < 1) {
{
response = 'Proper usage: dump [on/off/status]'; // Display correct command usage response = 'Proper usage: dump [on/off/status]'; // Display correct command usage
} }
else else {
{ switch (args['_'][0].toLowerCase()) {
switch(args['_'][0].toLowerCase())
{
case 'on': case 'on':
process.coreDumpLocation = process.platform == 'win32' ? process.execPath.replace('.exe', '.dmp') : (process.execPath + '.dmp'); process.coreDumpLocation = process.platform == 'win32' ? process.execPath.replace('.exe', '.dmp') : (process.execPath + '.dmp');
response = 'enabled'; response = 'enabled';
@ -1886,12 +1833,10 @@ function createMeshCore(agent)
response = 'disabled'; response = 'disabled';
break; break;
case 'status': case 'status':
if (process.coreDumpLocation) if (process.coreDumpLocation) {
{
response = 'Core Dump: [ENABLED' + (require('fs').existsSync(process.coreDumpLocation) ? (', (DMP file exists)]') : (']')); response = 'Core Dump: [ENABLED' + (require('fs').existsSync(process.coreDumpLocation) ? (', (DMP file exists)]') : (']'));
} }
else else {
{
response = 'Core Dump: [DISABLED]'; response = 'Core Dump: [DISABLED]';
} }
break; break;
@ -1911,18 +1856,14 @@ function createMeshCore(agent)
} }
case 'uninstallagent': case 'uninstallagent':
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
if (!require('service-manager').manager.getService(agentName).isMe()) if (!require('service-manager').manager.getService(agentName).isMe()) {
{
response = 'Uininstall failed, this instance is not the service instance'; response = 'Uininstall failed, this instance is not the service instance';
} }
else else {
{ try {
try
{
diagnosticAgent_uninstall(); diagnosticAgent_uninstall();
} }
catch(x) catch (x) {
{
} }
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();"; var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true }); this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
@ -2289,40 +2230,31 @@ function createMeshCore(agent)
} }
case 'diagnostic': case 'diagnostic':
{ {
if (!mesh.DAIPC.listening) if (!mesh.DAIPC.listening) {
{
response = 'Unable to bind to Diagnostic IPC, most likely because the path (' + process.cwd() + ') is not on a local file system'; response = 'Unable to bind to Diagnostic IPC, most likely because the path (' + process.cwd() + ') is not on a local file system';
break; break;
} }
var diag = diagnosticAgent_installCheck(); var diag = diagnosticAgent_installCheck();
if (diag) if (diag) {
{ if (args['_'].length == 1 && args['_'][0] == 'uninstall') {
if (args['_'].length == 1 && args['_'][0] == 'uninstall')
{
diagnosticAgent_uninstall(); diagnosticAgent_uninstall();
response = 'Diagnostic Agent uninstalled'; response = 'Diagnostic Agent uninstalled';
} }
else else {
{
response = 'Diagnostic Agent installed at: ' + diag.appLocation(); response = 'Diagnostic Agent installed at: ' + diag.appLocation();
} }
} }
else else {
{ if (args['_'].length == 1 && args['_'][0] == 'install') {
if (args['_'].length == 1 && args['_'][0] == 'install')
{
diag = diagnosticAgent_installCheck(true); diag = diagnosticAgent_installCheck(true);
if (diag) if (diag) {
{
response = 'Diagnostic agent was installed at: ' + diag.appLocation(); response = 'Diagnostic agent was installed at: ' + diag.appLocation();
} }
else else {
{
response = 'Diagnostic agent installation failed'; response = 'Diagnostic agent installation failed';
} }
} }
else else {
{
response = 'Diagnostic Agent Not installed. To install: diagnostic install'; response = 'Diagnostic Agent Not installed. To install: diagnostic install';
} }
} }
@ -2375,7 +2307,7 @@ function createMeshCore(agent)
case 'plugin': { case 'plugin': {
if (typeof args['_'][0] == 'string') { if (typeof args['_'][0] == 'string') {
try { try {
// pass off the action to the plugin // Pass off the action to the plugin
// for plugin creators, you'll want to have a plugindir/modules_meshcore/plugin.js // for plugin creators, you'll want to have a plugindir/modules_meshcore/plugin.js
// to control the output / actions here. // to control the output / actions here.
response = require(args['_'][0]).consoleaction(args, rights, sessionid, mesh); response = require(args['_'][0]).consoleaction(args, rights, sessionid, mesh);
@ -2385,7 +2317,6 @@ function createMeshCore(agent)
} else { } else {
response = 'Proper usage: plugin [pluginName] [args].'; response = 'Proper usage: plugin [pluginName] [args].';
} }
break; break;
} }
default: { // This is an unknown command, return an error message default: { // This is an unknown command, return an error message

View File

@ -1278,15 +1278,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
break; break;
} }
case 'plugin': { case 'plugin': {
if (typeof command.plugin == 'string') { if (typeof command.plugin != 'string') break;
try { try {
var pluginHandler = require('./pluginHandler.js').pluginHandler(parent.parent); var pluginHandler = require('./pluginHandler.js').pluginHandler(parent.parent);
pluginHandler.plugins[command.plugin].serveraction(command, obj, parent); pluginHandler.plugins[command.plugin].serveraction(command, obj, parent);
} catch (e) { } catch (e) {
console.log('Error loading plugin handler (' + e + ')'); console.log('Error loading plugin handler (' + e + ')');
} }
}
break; break;
} }
default: { default: {

View File

@ -31,6 +31,7 @@ function CreateMeshCentralServer(config, args) {
obj.swarmserver = null; obj.swarmserver = null;
obj.mailserver = null; obj.mailserver = null;
obj.amtEventHandler = null; obj.amtEventHandler = null;
obj.pluginHandler = null;
obj.amtScanner = null; obj.amtScanner = null;
obj.meshScanner = null; obj.meshScanner = null;
obj.letsencrypt = null; obj.letsencrypt = null;
@ -702,6 +703,11 @@ function CreateMeshCentralServer(config, args) {
return; return;
} }
// Start plugin manager if configuration allows this.
if ((obj.config) && (obj.config.settings) && (obj.config.settings.plugins != null)) {
obj.pluginHandler = require("./pluginHandler.js").pluginHandler(obj);
}
// Load the default meshcore and meshcmd // Load the default meshcore and meshcmd
obj.updateMeshCore(); obj.updateMeshCore();
obj.updateMeshCmd(); obj.updateMeshCmd();
@ -865,10 +871,8 @@ function CreateMeshCentralServer(config, args) {
// Dispatch an event that the server is now running // Dispatch an event that the server is now running
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' }); obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
obj.pluginHandler = require("./pluginHandler.js").pluginHandler(obj);
// Plugin hook. Need to run something at server startup? This is the place. // Plugin hook. Need to run something at server startup? This is the place.
obj.pluginHandler.callHook("server_startup"); if (obj.pluginHandler) { obj.pluginHandler.callHook("server_startup"); }
// Load the login cookie encryption key from the database if allowed // Load the login cookie encryption key from the database if allowed
if ((obj.config) && (obj.config.settings) && (obj.config.settings.allowlogintoken == true)) { if ((obj.config) && (obj.config.settings) && (obj.config.settings.allowlogintoken == true)) {
@ -1352,8 +1356,10 @@ function CreateMeshCentralServer(config, args) {
} }
} }
} }
obj.pluginHandler = require("./pluginHandler.js").pluginHandler(obj);
obj.pluginHandler.addMeshCoreModules(modulesAdd); // Add plugins to cores
if (obj.pluginHandler) { obj.pluginHandler.addMeshCoreModules(modulesAdd); }
// Merge the cores and compute the hashes // Merge the cores and compute the hashes
for (var i in modulesAdd) { for (var i in modulesAdd) {
if ((i == 'windows-recovery') || (i == 'linux-recovery')) { if ((i == 'windows-recovery') || (i == 'linux-recovery')) {

View File

@ -198,7 +198,11 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
if (xdevicename2 != null) { metadata.devicename = xdevicename2; } if (xdevicename2 != null) { metadata.devicename = xdevicename2; }
var firstBlock = JSON.stringify(metadata); var firstBlock = JSON.stringify(metadata);
recordingEntry(fd, 1, ((req.query.browser) ? 2 : 0), firstBlock, function () { recordingEntry(fd, 1, ((req.query.browser) ? 2 : 0), firstBlock, function () {
relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false }; try { relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false }; } catch (ex) {
try { ws.send('c'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded.
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
return;
}
try { ws.send('cr'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded. try { ws.send('cr'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded.
try { relayinfo.peer1.ws.send('cr'); } catch (ex) { } try { relayinfo.peer1.ws.send('cr'); } catch (ex) { }
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.4.1-y", "version": "0.4.1-z",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -23,17 +23,14 @@ module.exports.pluginHandler = function (parent) {
obj.pluginPath = obj.parent.path.join(obj.parent.datapath, 'plugins'); obj.pluginPath = obj.parent.path.join(obj.parent.datapath, 'plugins');
obj.plugins = {}; obj.plugins = {};
obj.exports = {}; obj.exports = {};
try {
obj.enabled = obj.parent.config.settings.plugins.enabled;
obj.loadList = obj.parent.config.settings.plugins.list; obj.loadList = obj.parent.config.settings.plugins.list;
} catch (e) { // Config file options not present, disable self
obj.enabled = false; if (typeof obj.loadList != 'object') {
obj.loadList = {}; obj.loadList = {};
console.log('Plugin options not added to the config file. Plugins disabled. Please see the documentation.'); console.log('Plugin list not specified, please fix configuration file.');
return null;
} }
if (obj.enabled) {
obj.loadList.forEach(function (plugin, index) { obj.loadList.forEach(function (plugin, index) {
if (obj.fs.existsSync(obj.pluginPath + '/' + plugin)) { if (obj.fs.existsSync(obj.pluginPath + '/' + plugin)) {
try { try {
@ -44,7 +41,6 @@ module.exports.pluginHandler = function (parent) {
} }
} }
}); });
}
obj.prepExports = function () { obj.prepExports = function () {
var str = 'function() {\r\n'; var str = 'function() {\r\n';
@ -57,7 +53,6 @@ module.exports.pluginHandler = function (parent) {
} }
} }
str += 'obj.enabled = '+ obj.enabled +';\r\n';
str += `obj.onDeviceRefeshEnd = function(nodeid, panel, refresh, event) { str += `obj.onDeviceRefeshEnd = function(nodeid, panel, refresh, event) {
for (const p of Object.keys(obj)) { for (const p of Object.keys(obj)) {
if (typeof obj[p].onDeviceRefreshEnd == 'function') { if (typeof obj[p].onDeviceRefreshEnd == 'function') {
@ -73,9 +68,7 @@ module.exports.pluginHandler = function (parent) {
}; };
obj.callPluginPage = function(id) { obj.callPluginPage = function(id) {
var pages = Q('p19pages').querySelectorAll("#p19pages>div"); var pages = Q('p19pages').querySelectorAll("#p19pages>div");
for (const i of pages) { for (const i of pages) { i.style.display = 'none'; }
i.style.display = 'none';
}
QV(id, true); QV(id, true);
}; };
return obj; };`; return obj; };`;
@ -95,7 +88,6 @@ module.exports.pluginHandler = function (parent) {
}; };
obj.addMeshCoreModules = function (modulesAdd) { obj.addMeshCoreModules = function (modulesAdd) {
if (obj.enabled !== true) return;
for (var plugin in obj.plugins) { for (var plugin in obj.plugins) {
var moduleDirPath = null; var moduleDirPath = null;
var modulesDir = null; var modulesDir = null;

File diff suppressed because one or more lines are too long

View File

@ -1036,7 +1036,8 @@
var sessionActivity = Date.now(); var sessionActivity = Date.now();
var updateSessionTimer = null; var updateSessionTimer = null;
var pluginHandlerBuilder = {{{pluginHandler}}}; var pluginHandlerBuilder = {{{pluginHandler}}};
var pluginHandler = new pluginHandlerBuilder(); var pluginHandler = null;
if (pluginHandlerBuilder != null) { pluginHandler = new pluginHandlerBuilder(); }
// Console Message Display Timers // Console Message Display Timers
var p11DeskConsoleMsgTimer = null; var p11DeskConsoleMsgTimer = null;
@ -2329,13 +2330,8 @@
break; break;
} }
case 'plugin': { case 'plugin': {
if (typeof message.plugin == 'string') { if ((pluginHandler == null) || (typeof message.plugin != 'string')) break;
try { try { pluginHandler[message.plugin][message.method](server, message); } catch (e) { console.log('Error loading plugin handler ('+ e + ')'); }
pluginHandler[message.plugin][message.method](server, message);
} catch (e) {
console.log('Error loading plugin handler ('+ e + ')');
}
}
break; break;
} }
default: default:
@ -4390,6 +4386,7 @@
QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess); QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess); QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess);
QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8)); QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
QV('MainDevPlugins', pluginHandler != null);
QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0)); QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0));
QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:''); QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
@ -4435,7 +4432,8 @@
p12clearConsoleMsg(); p12clearConsoleMsg();
p13clearConsoleMsg(); p13clearConsoleMsg();
pluginHandler.onDeviceRefeshEnd(nodeid, panel, refresh, event); // Device refresh plugin handler
if (pluginHandler != null) { pluginHandler.onDeviceRefeshEnd(nodeid, panel, refresh, event); }
} }
setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching. setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
if (!panel) panel = 10; if (!panel) panel = 10;
@ -9168,16 +9166,14 @@
// If we are going to panel 0 in "full screen mode", hide the left bar. // If we are going to panel 0 in "full screen mode", hide the left bar.
QV('topbar', x != 0); QV('topbar', x != 0);
if ((x == 0) && (webPageFullScreen)) { if ((x == 0) && (webPageFullScreen)) { QC('body').add("arg_hide"); }
QC('body').add("arg_hide");
}
QV('MainSubMenuSpan', x >= 10 && x < 20); QV('MainSubMenuSpan', x >= 10 && x < 20);
QV('UserDummyMenuSpan', (x < 10) && (x != 6) && webPageFullScreen); QV('UserDummyMenuSpan', (x < 10) && (x != 6) && webPageFullScreen);
QV('MeshSubMenuSpan', x >= 20 && x < 30); QV('MeshSubMenuSpan', x >= 20 && x < 30);
QV('UserSubMenuSpan', x >= 30 && x < 40); QV('UserSubMenuSpan', x >= 30 && x < 40);
QV('ServerSubMenuSpan', x == 6 || x == 115 || x == 40 || x == 41); QV('ServerSubMenuSpan', x == 6 || x == 115 || x == 40 || x == 41);
var panels = { 10: 'MainDev', 11: 'MainDevDesktop', 12: 'MainDevTerminal', 13: 'MainDevFiles', 14: 'MainDevAmt', 15: 'MainDevConsole', 16: 'MainDevEvents', 17: 'MainDevInfo', 20: 'MeshGeneral', 30: 'UserGeneral', 31: 'UserEvents', 6: 'ServerGeneral', 40: 'ServerStats', 41: 'ServerTrace', 19: 'Plugins', 115: 'ServerConsole' }; var panels = { 10: 'MainDev', 11: 'MainDevDesktop', 12: 'MainDevTerminal', 13: 'MainDevFiles', 14: 'MainDevAmt', 15: 'MainDevConsole', 16: 'MainDevEvents', 17: 'MainDevInfo', 19: 'MainDevPlugins', 20: 'MeshGeneral', 30: 'UserGeneral', 31: 'UserEvents', 6: 'ServerGeneral', 40: 'ServerStats', 41: 'ServerTrace', 115: 'ServerConsole' };
for (var i in panels) { for (var i in panels) {
QC(panels[i]).remove('style3x'); QC(panels[i]).remove('style3x');
QC(panels[i]).remove('style3sel'); QC(panels[i]).remove('style3sel');

View File

@ -1518,13 +1518,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Clean up the U2F challenge if needed // Clean up the U2F challenge if needed
if (req.session.u2fchallenge) { delete req.session.u2fchallenge; }; if (req.session.u2fchallenge) { delete req.session.u2fchallenge; };
var pluginHandler = require('./pluginHandler.js').pluginHandler(parent);
// Fetch the web state // Fetch the web state
parent.debug('web', 'handleRootRequestEx: success.'); parent.debug('web', 'handleRootRequestEx: success.');
obj.db.Get('ws' + user._id, function (err, states) { obj.db.Get('ws' + user._id, function (err, states) {
var webstate = (states.length == 1) ? states[0].state : ''; var webstate = (states.length == 1) ? states[0].state : '';
res.render(getRenderPage('default', req), { authCookie: authCookie, viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, extitle: encodeURIComponent(domain.title), extitle2: encodeURIComponent(domain.title2), domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: pluginHandler.prepExports() }); res.render(getRenderPage('default', req), { authCookie: authCookie, viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, extitle: encodeURIComponent(domain.title), extitle2: encodeURIComponent(domain.title2), domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null)?'null':parent.pluginHandler.prepExports() });
}); });
} else { } else {
// Send back the login application // Send back the login application