From 787e8ceaec2a50bdbd5ff4def84920c8af095098 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 22 Dec 2019 12:36:19 +0100 Subject: [PATCH 1/3] Fix "undefined" when downloading a backup --- webserver.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webserver.js b/webserver.js index e1e73951..882c8e11 100644 --- a/webserver.js +++ b/webserver.js @@ -2930,7 +2930,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { archive.on('error', function (err) { throw err; }); // Set the archive name - res.attachment(domain.title + '-Backup-' + new Date().toLocaleDateString().replace('/', '-').replace('/', '-') + '.zip'); + res.attachment((domain.title ? domain.title : "Meshcentral") + '-Backup-' + new Date().toLocaleDateString().replace('/', '-').replace('/', '-') + '.zip'); // Pipe archive data to the file archive.pipe(res); From 212ac81c6051484e7b00d7bb918f87d94fcada32 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 22 Dec 2019 12:37:24 +0100 Subject: [PATCH 2/3] Hide automatically run commands in the linux terminal --- agents/meshcore.js | 16 ++-- agents/meshcore.min.js | 106 +++++++++++++++++---------- public/scripts/amt-terminal-0.0.2.js | 4 +- 3 files changed, 80 insertions(+), 46 deletions(-) diff --git a/agents/meshcore.js b/agents/meshcore.js index 60b8e666..1fcd19e9 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1202,15 +1202,17 @@ function createMeshCore(agent) { { try { + var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } }; + if (fs.existsSync('/usr/bin/python') && fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("export TERM='xterm'\nalias ls='ls --color=auto'\nclear\n"); } + this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } } else if (fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); } + this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } } else { - this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8)?require('user-sessions').consoleUid():null }); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); } + this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\n"); } } } catch (e) { MeshServerLog("Failed to start remote terminal session, " + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest); @@ -2967,4 +2969,4 @@ try { } } catch (ex) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": "uncaughtException2: " + ex }); -} \ No newline at end of file +} diff --git a/agents/meshcore.min.js b/agents/meshcore.min.js index 32aae0c6..1fcd19e9 100644 --- a/agents/meshcore.min.js +++ b/agents/meshcore.min.js @@ -768,13 +768,20 @@ function createMeshCore(agent) { //sendConsoleText('setClip: ' + JSON.stringify(data)); if (typeof data.data == 'string') { MeshServerLog('Setting clipboard content, ' + data.data.length + ' byte(s)', data); - if (typeof data.data == 'string') { - if (require('MeshAgent').isService) { require('clipboard').dispatchWrite(data.data); } else { require("clipboard")(data.data); } // Set the clipboard - mesh.SendCommand({ "action": "msg", "type": "setclip", "sessionid": data.sessionid, "success": true }); - } + if (require('MeshAgent').isService) { require('clipboard').dispatchWrite(data.data); } else { require("clipboard")(data.data); } // Set the clipboard + mesh.SendCommand({ "action": "msg", "type": "setclip", "sessionid": data.sessionid, "success": true }); } break; } + case 'userSessions': { + // Send back current user sessions list, this is Windows only. + //sendConsoleText('userSessions: ' + JSON.stringify(data)); + if (process.platform != 'win32') break; + var p = require('user-sessions').enumerateUsers(); + p.sessionid = data.sessionid; + p.then(function (u) { mesh.SendCommand({ 'action': 'msg', 'type': 'userSessions', 'sessionid': u.sessionid, 'data': u }); }); + break; + } default: // Unknown action, ignore it. break; @@ -1088,6 +1095,7 @@ function createMeshCore(agent) { // Handle tunnel data 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) // Take a look at the protocol + if ((data.length > 3) && (data[0] == '{')) { onTunnelControlData(data, this); return; } this.httprequest.protocol = parseInt(data); if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; } if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6) || (this.httprequest.protocol == 8) || (this.httprequest.protocol == 9)) { @@ -1143,26 +1151,38 @@ function createMeshCore(agent) { else { // Logged in user - var username = require('user-sessions').getUsername(require('user-sessions').consoleUid()); - if (require('win-virtual-terminal').supported) + var userPromise = require('user-sessions').enumerateUsers(); + userPromise.that = this; + userPromise.then(function (u) { - // ConPTY PseudoTerminal - this.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (this.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } }); - } - else - { - // Legacy Terminal - this.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-terminal', script: getJSModule('win-terminal') }], launch: { module: 'win-terminal', method: (this.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } }); - } - this.httprequest._dispatcher.ws = this; - this.httprequest._dispatcher.on('connection', function (c) - { - console.log('client connected'); - this.ws._term = c; - c.pipe(this.ws, { dataTypeSkip: 1 }); - this.ws.pipe(c, { dataTypeSkip: 1, end: false }); - this.ws.prependListener('end', function () { this.httprequest._term.end(function () { console.log("Terminal was closed"); }); }); - }); + var that = this.that; + if (u.Active.length > 0) + { + var username = u.Active[0].Username; + if (require('win-virtual-terminal').supported) + { + // ConPTY PseudoTerminal + that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } }); + } + else + { + // Legacy Terminal + that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-terminal', script: getJSModule('win-terminal') }], launch: { module: 'win-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } }); + } + that.httprequest._dispatcher.ws = that; + that.httprequest._dispatcher.on('connection', function (c) + { + console.log('client connected'); + this.ws._term = c; + c.pipe(this.ws, { dataTypeSkip: 1 }); + this.ws.pipe(c, { dataTypeSkip: 1, end: false }); + this.ws.prependListener('end', function () + { + if (this.httprequest._term) { this.httprequest._term.end(function () { console.log("Terminal was closed"); }); } + }); + }); + } + }); } } catch (e) { @@ -1182,15 +1202,17 @@ function createMeshCore(agent) { { try { + var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } }; + if (fs.existsSync('/usr/bin/python') && fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("export TERM='xterm'\nalias ls='ls --color=auto'\nclear\n"); } + this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } } else if (fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null }); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("alias ls='ls --color=auto'\nclear\n"); } + this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } } else { - this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8)?require('user-sessions').consoleUid():null }); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\nclear\n"); } + this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\n"); } } } catch (e) { MeshServerLog("Failed to start remote terminal session, " + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest); @@ -1257,8 +1279,13 @@ function createMeshCore(agent) { return; } + // Look for a TSID + var tsid = null; + if ((this.httprequest.xoptions != null) && (typeof this.httprequest.xoptions.tsid == 'number')) { tsid = this.httprequest.xoptions.tsid; } + require('MeshAgent')._tsid = tsid; + // Remote desktop using native pipes - this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(require('MeshAgent')._tsid == null ? undefined : require('MeshAgent')._tsid), tunnel: this }; + this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(tsid), tunnel: this }; this.httprequest.desktop.kvm.parent = this.httprequest.desktop; this.desktop = this.httprequest.desktop; @@ -1739,7 +1766,12 @@ function createMeshCore(agent) { return; } - if (obj.type == 'close') { + if (obj.type == 'options') { + // These are additional connection options passed in the control channel. + //sendConsoleText('options: ' + JSON.stringify(obj)); + delete obj.type; + ws.httprequest.xoptions = obj; + } else if (obj.type == 'close') { // We received the close on the websocket //sendConsoleText('Tunnel #' + ws.tunnel.index + ' WebSocket control close'); try { ws.close(); } catch (e) { } @@ -1871,7 +1903,7 @@ function createMeshCore(agent) { var response = null; switch (cmd) { case 'help': { // Displays available commands - 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,wallpaper'; + var fin = '', f = '', availcommands = 'version,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,wallpaper'; if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration'; @@ -1885,6 +1917,9 @@ function createMeshCore(agent) { response = 'Available commands: \r\n' + fin + '.'; break; } + case 'version': + response = 'Mesh Agent Version: ' + process.versions.meshAgent; + break; case 'wpfhwacceleration': if (process.platform != 'win32') { throw ('wpfhwacceleration setting is only supported on Windows'); } if (args['_'].length != 1) @@ -1979,10 +2014,7 @@ function createMeshCore(agent) { var v = []; for(var i in u) { - if(u[i].State == 'Active' || u[i].State == 'Connected') - { - v.push({ tsid: i, type: u[i].StationName, user: u[i].Username }); - } + if(u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); } } sendConsoleText(JSON.stringify(v, null, 1), this.sessionid); }); @@ -2937,4 +2969,4 @@ try { } } catch (ex) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": "uncaughtException2: " + ex }); -} \ No newline at end of file +} diff --git a/public/scripts/amt-terminal-0.0.2.js b/public/scripts/amt-terminal-0.0.2.js index ea42e210..d807ecfd 100644 --- a/public/scripts/amt-terminal-0.0.2.js +++ b/public/scripts/amt-terminal-0.0.2.js @@ -73,7 +73,7 @@ var CreateAmtRemoteTerminal = function (divid, options) { } obj.xxStateChange = function (newstate) { - if ((newstate == 3) && (options != null) && (options.xterm == true)) { obj.TermSendKeys('stty rows ' + obj.height + ' cols ' + obj.width + '\nclear\n'); } + if ((newstate == 3) && (options != null) && (options.xterm == true)) { obj.TermSendKeys(' stty rows ' + obj.height + ' cols ' + obj.width + '\n clear\n'); } } obj.ProcessData = function (str) { @@ -807,4 +807,4 @@ var CreateAmtRemoteTerminal = function (divid, options) { obj.DivElement.style['height'] = ''; if ((options != null) && (options.width != null) && (options.height != null)) { obj.Init(options.width, options.height); } else { obj.Init(); } return obj; -} \ No newline at end of file +} From e33fab40c3c01454c991ab5408954ea9facafb4a Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 22 Dec 2019 13:59:24 +0100 Subject: [PATCH 3/3] Interactive terminal without python --- agents/meshcore.js | 37 ++++++++++++++++++++++++++----------- agents/meshcore.min.js | 37 ++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/agents/meshcore.js b/agents/meshcore.js index 1fcd19e9..c6873489 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1184,8 +1184,7 @@ function createMeshCore(agent) { } }); } - } catch (e) - { + } catch (e) { 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.end(); @@ -1202,17 +1201,33 @@ function createMeshCore(agent) { { try { - var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } }; + var bash = fs.existsSync('/bin/bash') ? '/bin/bash' : false; + var sh = fs.existsSync('/bin/sh') ? '/bin/sh' : false; + var script = fs.existsSync('/usr/bin/script') ? '/usr/bin/script' : false; + var python = fs.existsSync('/usr/bin/python') ? '/usr/bin/python' : false; + var shell = bash || sh; - if (fs.existsSync('/usr/bin/python') && fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], options); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } - } else if (fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], options); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } + var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } }; + var setupcommands = " alias ls='ls --color=auto'\n"; + if (shell == sh) setupcommands += "stty erase ^H\n" + + if (script && shell) { + this.httprequest.process = childProcess.execFile(script, ['script', '--return', '--quiet', '-c', '"' + shell + '"', '/dev/null'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); } + } else if (python && shell) { + this.httprequest.process = childProcess.execFile(python, ['python', '-c', 'import pty; pty.spawn(["' + shell + '"])'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); } + } else if (bash) { + options.type = childProcess.SpawnTypes.TERM; + this.httprequest.process = childProcess.execFile(bash, ['bash', '-i'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); } + } else if (sh) { + options.type = childProcess.SpawnTypes.TERM; + this.httprequest.process = childProcess.execFile(sh, ['sh'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands + "PS1='$ '\n"); } } else { - this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], options); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\n"); } + MeshServerLog("Failed to start remote terminal session, no shell found"); + return; } } catch (e) { MeshServerLog("Failed to start remote terminal session, " + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest); diff --git a/agents/meshcore.min.js b/agents/meshcore.min.js index 1fcd19e9..c6873489 100644 --- a/agents/meshcore.min.js +++ b/agents/meshcore.min.js @@ -1184,8 +1184,7 @@ function createMeshCore(agent) { } }); } - } catch (e) - { + } catch (e) { 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.end(); @@ -1202,17 +1201,33 @@ function createMeshCore(agent) { { try { - var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } }; + var bash = fs.existsSync('/bin/bash') ? '/bin/bash' : false; + var sh = fs.existsSync('/bin/sh') ? '/bin/sh' : false; + var script = fs.existsSync('/usr/bin/script') ? '/usr/bin/script' : false; + var python = fs.existsSync('/usr/bin/python') ? '/usr/bin/python' : false; + var shell = bash || sh; - if (fs.existsSync('/usr/bin/python') && fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/usr/bin/python', ['python', '-c', "import pty; pty.spawn([\"/bin/bash\"])"], options); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } - } else if (fs.existsSync('/bin/bash')) { - this.httprequest.process = childProcess.execFile('/bin/bash', ['bash', '-i'], options); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write(" alias ls='ls --color=auto'\n"); } + var options = { uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: { HISTCONTROL: "ignoreboth", TERM: "xterm" } }; + var setupcommands = " alias ls='ls --color=auto'\n"; + if (shell == sh) setupcommands += "stty erase ^H\n" + + if (script && shell) { + this.httprequest.process = childProcess.execFile(script, ['script', '--return', '--quiet', '-c', '"' + shell + '"', '/dev/null'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); } + } else if (python && shell) { + this.httprequest.process = childProcess.execFile(python, ['python', '-c', 'import pty; pty.spawn(["' + shell + '"])'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); } + } else if (bash) { + options.type = childProcess.SpawnTypes.TERM; + this.httprequest.process = childProcess.execFile(bash, ['bash', '-i'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands); } + } else if (sh) { + options.type = childProcess.SpawnTypes.TERM; + this.httprequest.process = childProcess.execFile(sh, ['sh'], options); // Start as active user + if (process.platform == 'linux') { this.httprequest.process.stdin.write(setupcommands + "PS1='$ '\n"); } } else { - this.httprequest.process = childProcess.execFile('/bin/sh', ['sh'], options); // Start as active user - if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nPS1='\\u@\\h:\\w\\$ '\n"); } + MeshServerLog("Failed to start remote terminal session, no shell found"); + return; } } catch (e) { MeshServerLog("Failed to start remote terminal session, " + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);