mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-04-19 02:05:21 -04:00
Added remote process control
This commit is contained in:
parent
d05f086a0e
commit
fb55e44edf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -30,6 +30,7 @@ function createMeshCore(agent) {
|
|||||||
var net = require('net');
|
var net = require('net');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var rtc = require('ILibWebRTC');
|
var rtc = require('ILibWebRTC');
|
||||||
|
var processManager = require('process-manager');
|
||||||
var SMBiosTables = require('smbios');
|
var SMBiosTables = require('smbios');
|
||||||
var amtMei = null, amtLms = null, amtLmsState = 0;
|
var amtMei = null, amtLms = null, amtLmsState = 0;
|
||||||
var amtMeiConnected = 0, amtMeiTmpState = null;
|
var amtMeiConnected = 0, amtMeiTmpState = null;
|
||||||
@ -327,39 +328,55 @@ function createMeshCore(agent) {
|
|||||||
// If this is a console command, parse it and call the console handler
|
// If this is a console command, parse it and call the console handler
|
||||||
switch (data.action) {
|
switch (data.action) {
|
||||||
case 'msg': {
|
case 'msg': {
|
||||||
if (data.type == 'console') { // Process a console command
|
switch (data.type) {
|
||||||
if (data.value && data.sessionid) {
|
case 'console': { // Process a console command
|
||||||
var args = splitArgs(data.value);
|
if (data.value && data.sessionid) {
|
||||||
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
|
var args = splitArgs(data.value);
|
||||||
|
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'tunnel': {
|
||||||
|
if (data.value != null) { // Process a new tunnel connection request
|
||||||
|
// Create a new tunnel object
|
||||||
|
var xurl = getServerTargetUrlEx(data.value);
|
||||||
|
if (xurl != null) {
|
||||||
|
var woptions = http.parseUri(xurl);
|
||||||
|
woptions.rejectUnauthorized = 0;
|
||||||
|
//sendConsoleText(JSON.stringify(woptions));
|
||||||
|
var tunnel = http.request(woptions);
|
||||||
|
tunnel.upgrade = onTunnelUpgrade;
|
||||||
|
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
|
||||||
|
tunnel.sessionid = data.sessionid;
|
||||||
|
tunnel.rights = data.rights;
|
||||||
|
tunnel.state = 0;
|
||||||
|
tunnel.url = xurl;
|
||||||
|
tunnel.protocol = 0;
|
||||||
|
tunnel.tcpaddr = data.tcpaddr;
|
||||||
|
tunnel.tcpport = data.tcpport;
|
||||||
|
tunnel.end();
|
||||||
|
// Put the tunnel in the tunnels list
|
||||||
|
var index = nextTunnelIndex++;;
|
||||||
|
tunnel.index = index;
|
||||||
|
tunnels[index] = tunnel;
|
||||||
|
|
||||||
|
sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'ps': {
|
||||||
|
if (data.sessionid) {
|
||||||
|
processManager.getProcesses(function (plist) { mesh.SendCommand({ "action": "msg", "type": "ps", "value": JSON.stringify(plist), "sessionid": data.sessionid }); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'pskill': {
|
||||||
|
sendConsoleText(JSON.stringify(data));
|
||||||
|
try { process.kill(data.value); } catch (e) { sendConsoleText(JSON.stringify(e)); }
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((data.type == 'tunnel') && (data.value != null)) { // Process a new tunnel connection request
|
|
||||||
// Create a new tunnel object
|
|
||||||
var xurl = getServerTargetUrlEx(data.value);
|
|
||||||
if (xurl != null) {
|
|
||||||
var woptions = http.parseUri(xurl);
|
|
||||||
woptions.rejectUnauthorized = 0;
|
|
||||||
//sendConsoleText(JSON.stringify(woptions));
|
|
||||||
var tunnel = http.request(woptions);
|
|
||||||
tunnel.upgrade = onTunnelUpgrade;
|
|
||||||
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
|
|
||||||
tunnel.sessionid = data.sessionid;
|
|
||||||
tunnel.rights = data.rights;
|
|
||||||
tunnel.state = 0;
|
|
||||||
tunnel.url = xurl;
|
|
||||||
tunnel.protocol = 0;
|
|
||||||
tunnel.tcpaddr = data.tcpaddr;
|
|
||||||
tunnel.tcpport = data.tcpport;
|
|
||||||
tunnel.end();
|
|
||||||
// Put the tunnel in the tunnels list
|
|
||||||
var index = nextTunnelIndex++;;
|
|
||||||
tunnel.index = index;
|
|
||||||
tunnels[index] = tunnel;
|
|
||||||
|
|
||||||
sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 'wakeonlan': {
|
case 'wakeonlan': {
|
||||||
// Send wake-on-lan on all interfaces for all MAC addresses in data.macs array. The array is a list of HEX MAC addresses.
|
// Send wake-on-lan on all interfaces for all MAC addresses in data.macs array. The array is a list of HEX MAC addresses.
|
||||||
@ -819,7 +836,7 @@ function createMeshCore(agent) {
|
|||||||
var response = null;
|
var response = null;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 'help': { // Displays available commands
|
case 'help': { // Displays available commands
|
||||||
response = 'Available commands: help, info, args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios.';
|
response = 'Available commands: help, info, args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, ps, kill, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios.';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'setdebug': {
|
case 'setdebug': {
|
||||||
@ -827,6 +844,23 @@ function createMeshCore(agent) {
|
|||||||
else { if (args['_'][0] == '*') { console.setDestination(1); } else { console.setDestination(parseInt(args['_'][0]), sessionid); } }
|
else { if (args['_'][0] == '*') { console.setDestination(1); } else { console.setDestination(parseInt(args['_'][0]), sessionid); } }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'ps': {
|
||||||
|
processManager.getProcesses(function (plist) {
|
||||||
|
var x = '';
|
||||||
|
for (var i in plist) { x += i + ', ' + plist[i].cmd + ((plist[i].user) ? (', ' + plist[i].user):'') + '\r\n'; }
|
||||||
|
sendConsoleText(x, sessionid);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'kill': {
|
||||||
|
if ((args['_'].length < 1)) {
|
||||||
|
response = 'Proper usage: kill [pid]'; // Display correct command usage
|
||||||
|
} else {
|
||||||
|
process.kill(parseInt(args['_'][0]));
|
||||||
|
response = 'Killed process ' + args['_'][0] + '.';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'smbios': {
|
case 'smbios': {
|
||||||
if (SMBiosTables != null) {
|
if (SMBiosTables != null) {
|
||||||
SMBiosTables.get(function (data) {
|
SMBiosTables.get(function (data) {
|
||||||
|
102
agents/modules_meshcmd/UserSessions.js
Normal file
102
agents/modules_meshcmd/UserSessions.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
|
||||||
|
|
||||||
|
function UserSessions()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'UserSessions';
|
||||||
|
|
||||||
|
if (process.platform == 'win32') {
|
||||||
|
this._marshal = require('_GenericMarshal');
|
||||||
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||||
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||||
|
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||||
|
this._wts.CreateMethod('WTSFreeMemory');
|
||||||
|
this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init'];
|
||||||
|
this.InfoClass =
|
||||||
|
{
|
||||||
|
'WTSInitialProgram': 0,
|
||||||
|
'WTSApplicationName': 1,
|
||||||
|
'WTSWorkingDirectory': 2,
|
||||||
|
'WTSOEMId': 3,
|
||||||
|
'WTSSessionId': 4,
|
||||||
|
'WTSUserName': 5,
|
||||||
|
'WTSWinStationName': 6,
|
||||||
|
'WTSDomainName': 7,
|
||||||
|
'WTSConnectState': 8,
|
||||||
|
'WTSClientBuildNumber': 9,
|
||||||
|
'WTSClientName': 10,
|
||||||
|
'WTSClientDirectory': 11,
|
||||||
|
'WTSClientProductId': 12,
|
||||||
|
'WTSClientHardwareId': 13,
|
||||||
|
'WTSClientAddress': 14,
|
||||||
|
'WTSClientDisplay': 15,
|
||||||
|
'WTSClientProtocolType': 16,
|
||||||
|
'WTSIdleTime': 17,
|
||||||
|
'WTSLogonTime': 18,
|
||||||
|
'WTSIncomingBytes': 19,
|
||||||
|
'WTSOutgoingBytes': 20,
|
||||||
|
'WTSIncomingFrames': 21,
|
||||||
|
'WTSOutgoingFrames': 22,
|
||||||
|
'WTSClientInfo': 23,
|
||||||
|
'WTSSessionInfo': 24,
|
||||||
|
'WTSSessionInfoEx': 25,
|
||||||
|
'WTSConfigInfo': 26,
|
||||||
|
'WTSValidationInfo': 27,
|
||||||
|
'WTSSessionAddressV4': 28,
|
||||||
|
'WTSIsRemoteSession': 29
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
|
||||||
|
{
|
||||||
|
var buffer = this._marshal.CreatePointer();
|
||||||
|
var bytesReturned = this._marshal.CreateVariable(4);
|
||||||
|
|
||||||
|
if (this._wts.WTSQuerySessionInformationA(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSQuerySessionInformation: ' + this._kernel32.GetLastError.Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
var retVal = buffer.Deref().String;
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(buffer.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Current = function Current()
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
var pinfo = this._marshal.CreatePointer();
|
||||||
|
var count = this._marshal.CreateVariable(4);
|
||||||
|
if (this._wts.WTSEnumerateSessionsA(0, 0, 1, pinfo, count).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSEnumerateSessionsA: ' + this._kernel32.GetLastError().Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count.toBuffer().readUInt32LE() ; ++i)
|
||||||
|
{
|
||||||
|
var info = pinfo.Deref().Deref(i * (this._marshal.PointerSize == 4 ? 12 : 24), this._marshal.PointerSize == 4 ? 12 : 24);
|
||||||
|
var j = { SessionId: info.toBuffer().readUInt32LE() };
|
||||||
|
j.StationName = info.Deref(this._marshal.PointerSize == 4 ? 4 : 8, this._marshal.PointerSize).Deref().String;
|
||||||
|
j.State = this.SessionStates[info.Deref(this._marshal.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE()];
|
||||||
|
if (j.State == 'Active') {
|
||||||
|
j.Username = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSUserName);
|
||||||
|
j.Domain = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSDomainName);
|
||||||
|
}
|
||||||
|
retVal[j.SessionId] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.Current = function Current()
|
||||||
|
{
|
||||||
|
return ({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new UserSessions();
|
102
agents/modules_meshcore/UserSessions.js
Normal file
102
agents/modules_meshcore/UserSessions.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
|
||||||
|
|
||||||
|
function UserSessions()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'UserSessions';
|
||||||
|
|
||||||
|
if (process.platform == 'win32') {
|
||||||
|
this._marshal = require('_GenericMarshal');
|
||||||
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||||
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||||
|
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||||
|
this._wts.CreateMethod('WTSFreeMemory');
|
||||||
|
this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init'];
|
||||||
|
this.InfoClass =
|
||||||
|
{
|
||||||
|
'WTSInitialProgram': 0,
|
||||||
|
'WTSApplicationName': 1,
|
||||||
|
'WTSWorkingDirectory': 2,
|
||||||
|
'WTSOEMId': 3,
|
||||||
|
'WTSSessionId': 4,
|
||||||
|
'WTSUserName': 5,
|
||||||
|
'WTSWinStationName': 6,
|
||||||
|
'WTSDomainName': 7,
|
||||||
|
'WTSConnectState': 8,
|
||||||
|
'WTSClientBuildNumber': 9,
|
||||||
|
'WTSClientName': 10,
|
||||||
|
'WTSClientDirectory': 11,
|
||||||
|
'WTSClientProductId': 12,
|
||||||
|
'WTSClientHardwareId': 13,
|
||||||
|
'WTSClientAddress': 14,
|
||||||
|
'WTSClientDisplay': 15,
|
||||||
|
'WTSClientProtocolType': 16,
|
||||||
|
'WTSIdleTime': 17,
|
||||||
|
'WTSLogonTime': 18,
|
||||||
|
'WTSIncomingBytes': 19,
|
||||||
|
'WTSOutgoingBytes': 20,
|
||||||
|
'WTSIncomingFrames': 21,
|
||||||
|
'WTSOutgoingFrames': 22,
|
||||||
|
'WTSClientInfo': 23,
|
||||||
|
'WTSSessionInfo': 24,
|
||||||
|
'WTSSessionInfoEx': 25,
|
||||||
|
'WTSConfigInfo': 26,
|
||||||
|
'WTSValidationInfo': 27,
|
||||||
|
'WTSSessionAddressV4': 28,
|
||||||
|
'WTSIsRemoteSession': 29
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
|
||||||
|
{
|
||||||
|
var buffer = this._marshal.CreatePointer();
|
||||||
|
var bytesReturned = this._marshal.CreateVariable(4);
|
||||||
|
|
||||||
|
if (this._wts.WTSQuerySessionInformationA(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSQuerySessionInformation: ' + this._kernel32.GetLastError.Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
var retVal = buffer.Deref().String;
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(buffer.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Current = function Current()
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
var pinfo = this._marshal.CreatePointer();
|
||||||
|
var count = this._marshal.CreateVariable(4);
|
||||||
|
if (this._wts.WTSEnumerateSessionsA(0, 0, 1, pinfo, count).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSEnumerateSessionsA: ' + this._kernel32.GetLastError().Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count.toBuffer().readUInt32LE() ; ++i)
|
||||||
|
{
|
||||||
|
var info = pinfo.Deref().Deref(i * (this._marshal.PointerSize == 4 ? 12 : 24), this._marshal.PointerSize == 4 ? 12 : 24);
|
||||||
|
var j = { SessionId: info.toBuffer().readUInt32LE() };
|
||||||
|
j.StationName = info.Deref(this._marshal.PointerSize == 4 ? 4 : 8, this._marshal.PointerSize).Deref().String;
|
||||||
|
j.State = this.SessionStates[info.Deref(this._marshal.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE()];
|
||||||
|
if (j.State == 'Active') {
|
||||||
|
j.Username = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSUserName);
|
||||||
|
j.Domain = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSDomainName);
|
||||||
|
}
|
||||||
|
retVal[j.SessionId] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.Current = function Current()
|
||||||
|
{
|
||||||
|
return ({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new UserSessions();
|
96
agents/modules_meshcore/process-manager.js
Normal file
96
agents/modules_meshcore/process-manager.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
|
||||||
|
function processManager() {
|
||||||
|
this._ObjectID = 'processManager';
|
||||||
|
switch (process.platform) {
|
||||||
|
case 'win32':
|
||||||
|
this._kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._kernel32.CreateMethod('CreateToolhelp32Snapshot');
|
||||||
|
this._kernel32.CreateMethod('Process32First');
|
||||||
|
this._kernel32.CreateMethod('Process32Next');
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
this._childProcess = require('child_process');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw (process.platform + ' not supported');
|
||||||
|
}
|
||||||
|
this.getProcesses = function getProcesses(callback) {
|
||||||
|
switch (process.platform) {
|
||||||
|
case 'win32':
|
||||||
|
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0), info = GM.CreateVariable(304), retVal = {};
|
||||||
|
info.toBuffer().writeUInt32LE(304, 0);
|
||||||
|
var nextProcess = this._kernel32.Process32First(h, info);
|
||||||
|
while (nextProcess.Val) {
|
||||||
|
retVal[info.Deref(8, 4).toBuffer().readUInt32LE(0)] = { cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String };
|
||||||
|
nextProcess = this._kernel32.Process32Next(h, info);
|
||||||
|
}
|
||||||
|
if (callback) { callback.apply(this, [retVal]); }
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
if (!this._psp) { this._psp = {}; }
|
||||||
|
var p = this._childProcess.execFile("/bin/ps", ["ps", "-uxa"], { type: this._childProcess.SpawnTypes.TERM });
|
||||||
|
this._psp[p.pid] = p;
|
||||||
|
p.Parent = this;
|
||||||
|
p.ps = '';
|
||||||
|
p.callback = callback;
|
||||||
|
p.args = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||||
|
p.on('exit', function onGetProcesses() {
|
||||||
|
delete this.Parent._psp[this.pid];
|
||||||
|
var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
||||||
|
for (var i in lines) {
|
||||||
|
var tokens = lines[i].split(' '), tokenList = [];
|
||||||
|
for (var x in tokens) {
|
||||||
|
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
||||||
|
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]); }
|
||||||
|
}
|
||||||
|
if ((i > 0) && (tokenList[key.PID])) {
|
||||||
|
retVal[tokenList[key.PID]] = { user: tokenList[key.USER], cmd: tokenList[key.COMMAND] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.callback) {
|
||||||
|
this.args.unshift(retVal);
|
||||||
|
this.callback.apply(this.parent, this.args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.getProcessInfo = function getProcessInfo(pid) {
|
||||||
|
switch (process.platform) {
|
||||||
|
case 'linux':
|
||||||
|
var status = require('fs').readFileSync('/proc/' + pid + '/status'), lines = status.toString().split('\n'), info = {};
|
||||||
|
for (var i in lines) {
|
||||||
|
var tokens = lines[i].split(':');
|
||||||
|
if (tokens.length > 1) { tokens[1] = tokens[1].trim(); }
|
||||||
|
info[tokens[0]] = tokens[1];
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
default:
|
||||||
|
throw ('getProcessInfo() not supported for ' + process.platform);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new processManager();
|
@ -651,9 +651,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
|||||||
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||||
if (obj.common.validateString(command.devicename, 1, 256) == false) break; // Check device name
|
if (obj.common.validateString(command.devicename, 1, 256) == false) break; // Check device name
|
||||||
if (obj.common.validateString(command.hostname, 1, 256) == false) break; // Check hostname
|
if (obj.common.validateString(command.hostname, 1, 256) == false) break; // Check hostname
|
||||||
if (obj.common.validateString(command.amtusername, 1, 16) == false) break; // Check username
|
if (obj.common.validateString(command.amtusername, 0, 16) == false) break; // Check username
|
||||||
if (obj.common.validateString(command.amtpassword, 1, 16) == false) break; // Check password
|
if (obj.common.validateString(command.amtpassword, 0, 16) == false) break; // Check password
|
||||||
if (obj.common.validateInt(command.amttls, 0, 1) == false) break; // Check TLS flag
|
if (command.amttls == '0') { command.amttls = 0; } else if (command.amttls == '1') { command.amttls = 1; } // Check TLS flag
|
||||||
|
if ((command.amttls != 1) && (command.amttls != 0)) break;
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
var mesh = obj.parent.meshes[command.meshid];
|
var mesh = obj.parent.meshes[command.meshid];
|
||||||
@ -667,7 +668,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
|||||||
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
||||||
// create the new node
|
// create the new node
|
||||||
var nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');;
|
var nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');;
|
||||||
var device = { type: 'node', mtype: 1, _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: parseInt(command.amttls) } };
|
var device = { type: 'node', mtype: 1, _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } };
|
||||||
obj.db.Set(device);
|
obj.db.Set(device);
|
||||||
|
|
||||||
// Event the new node
|
// Event the new node
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.1.6-a",
|
"version": "0.1.6-c",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -513,4 +513,12 @@ a {
|
|||||||
|
|
||||||
.notification:hover {
|
.notification:hover {
|
||||||
background-color: #EFE8B6;
|
background-color: #EFE8B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deskToolsBar {
|
||||||
|
padding:3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deskToolsBar:hover {
|
||||||
|
background-color: #EFE8B6;
|
||||||
}
|
}
|
@ -360,12 +360,21 @@
|
|||||||
<div id="DeskParent">
|
<div id="DeskParent">
|
||||||
<canvas id="Desk" width="640" height="200" style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></canvas>
|
<canvas id="Desk" width="640" height="200" style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="DeskTools" style="position:absolute;width:400px;height:100%;background-color:gray;top:0;right:0;border-left:2px solid lightgray;display:none">
|
||||||
|
<a id="DeskToolsRefreshButton" style="float:right;padding:3px;cursor:pointer" onclick="refreshDeskTools()">Refresh</a>
|
||||||
|
<div id="DeskToolsBar" style="position:absolute;padding:3px;border-radius: 3px 3px 0px 0px;top:5px;left:4px;bottom:26px;background-color:lightgray;cursor:pointer">Processes</div>
|
||||||
|
<div style="position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:lightgray;text-align:left">
|
||||||
|
<div style="border-bottom:1px solid darkgray;padding:3px"><a style=width:50px;padding-right:5px;float:left;cursor:pointer title="Sort by process id" onclick=sortProcess(0)>PID</a><a style=cursor:pointer title="Sort by name" onclick=sortProcess(1)>Name</a></div>
|
||||||
|
<div id="DeskToolsProcesses" style="overflow-y:scroll;position:absolute;top:24px;bottom:0px;width:100%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id=deskarea4>
|
<tr id=deskarea4>
|
||||||
<td style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
|
<td style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
|
||||||
<div style="float:right;text-align:right">
|
<div style="float:right;text-align:right">
|
||||||
<select id="termdisplays" style="display:none" onchange="deskSetDisplay(event)" onclick="deskGetDisplayNumbers(event)"></select>
|
<select id="termdisplays" style="display:none" onchange="deskSetDisplay(event)" onclick="deskGetDisplayNumbers(event)"></select>
|
||||||
|
<input id="DeskToolsButton" type="button" value="Tools" title="Toggle tools view" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
@ -969,11 +978,13 @@
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
// Node was found, dispatch the message
|
// Node was found, dispatch the message
|
||||||
if (message.type == 'console') { p15consoleReceive(nodes[index], message.value); } // This is a console message.
|
if (message.type == 'console') { p15consoleReceive(nodes[index], message.value); } // This is a console message.
|
||||||
if (message.type == 'notify') { // This is a notification message.
|
else if (message.type == 'notify') { // This is a notification message.
|
||||||
var n = { text:message.value };
|
var n = { text:message.value };
|
||||||
if (message.nodeid != null) { n.nodeid = message.nodeid; }
|
if (message.nodeid != null) { n.nodeid = message.nodeid; }
|
||||||
if (message.tag != null) { n.tag = message.tag; }
|
if (message.tag != null) { n.tag = message.tag; }
|
||||||
addNotification(n);
|
addNotification(n);
|
||||||
|
} else if (message.type == 'ps') {
|
||||||
|
showDeskToolsProcesses(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2823,6 +2834,10 @@
|
|||||||
|
|
||||||
// Request the power timeline
|
// Request the power timeline
|
||||||
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
||||||
|
|
||||||
|
// Reset the desktop tools
|
||||||
|
QV('DeskTools', false);
|
||||||
|
showDeskToolsProcesses();
|
||||||
}
|
}
|
||||||
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;
|
||||||
@ -3168,15 +3183,16 @@
|
|||||||
// Show and enable the right buttons
|
// Show and enable the right buttons
|
||||||
function updateDesktopButtons() {
|
function updateDesktopButtons() {
|
||||||
var mesh = meshes[currentNode.meshid];
|
var mesh = meshes[currentNode.meshid];
|
||||||
var deskState = ((desktop != null) && (desktop.state != 0));
|
var deskState = 0;
|
||||||
|
if (desktop != null) { deskState = desktop.State; }
|
||||||
|
|
||||||
// Show the right buttons
|
// Show the right buttons
|
||||||
QV('disconnectbutton1span', (deskState == true));
|
QV('disconnectbutton1span', (deskState != 0));
|
||||||
QV('connectbutton1span', (deskState == false) && (mesh.mtype == 2));
|
QV('connectbutton1span', (deskState == 0) && (mesh.mtype == 2));
|
||||||
QV('connectbutton1hspan', (deskState == false) && (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))));
|
QV('connectbutton1hspan', (deskState == 0) && (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))));
|
||||||
|
|
||||||
// Show the right settings
|
// Show the right settings
|
||||||
QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == false) || (desktop.contype == 2)));
|
QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2)));
|
||||||
QV('d7meshkvm', (mesh.mtype == 2) && ((deskState == false) || (desktop.contype == 1)));
|
QV('d7meshkvm', (mesh.mtype == 2) && ((deskState == false) || (desktop.contype == 1)));
|
||||||
|
|
||||||
// Enable buttons
|
// Enable buttons
|
||||||
@ -3184,6 +3200,11 @@
|
|||||||
QE('connectbutton1', online);
|
QE('connectbutton1', online);
|
||||||
var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
|
var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
|
||||||
QE('connectbutton1h', hwonline);
|
QE('connectbutton1h', hwonline);
|
||||||
|
QE('deskSaveBtn', deskState == 3);
|
||||||
|
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
|
||||||
|
QE('DeskCAD', deskState == 3);
|
||||||
|
QE('DeskToolsButton', online);
|
||||||
|
if (online == false) QV('DeskTools', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
@ -3232,12 +3253,9 @@
|
|||||||
var xstate = state;
|
var xstate = state;
|
||||||
if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
|
if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
|
||||||
var str = StatusStrs[xstate];
|
var str = StatusStrs[xstate];
|
||||||
if (desktop.webRtcActive == true) { str += ', WebRTC'; }
|
if ((desktop != null) && (desktop.webRtcActive == true)) { str += ', WebRTC'; }
|
||||||
//if (desktop.m.stopInput == true) { str += ', Loopback'; }
|
//if (desktop.m.stopInput == true) { str += ', Loopback'; }
|
||||||
QH('deskstatus', str);
|
QH('deskstatus', str);
|
||||||
QE('deskSaveBtn', state == 3);
|
|
||||||
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (state != 0) && (desktopsettings.showfocus));
|
|
||||||
QE('DeskCAD', state == 3);
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
// Disconnect and clean up the remote desktop
|
// Disconnect and clean up the remote desktop
|
||||||
@ -3364,6 +3382,44 @@
|
|||||||
desktop.m.sendcad();
|
desktop.m.sendcad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show process dialogs
|
||||||
|
function toggleDeskTools() {
|
||||||
|
if (xxdialogMode) return;
|
||||||
|
if (QS('DeskTools').display == 'none') {
|
||||||
|
QV('DeskTools', true);
|
||||||
|
Q('DeskTools').nodeid = currentNode._id;
|
||||||
|
refreshDeskTools();
|
||||||
|
} else {
|
||||||
|
QV('DeskTools', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh all of the desktop tool panels
|
||||||
|
function refreshDeskTools() {
|
||||||
|
QV('DeskToolsRefreshButton', false);
|
||||||
|
setTimeout(refreshDeskToolsEx, 500);
|
||||||
|
meshserver.send({ action: 'msg', type:'ps', nodeid: currentNode._id });
|
||||||
|
}
|
||||||
|
function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
|
||||||
|
var deskTools = { sort: 1, msg: null };
|
||||||
|
function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
|
||||||
|
function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return 0; }
|
||||||
|
function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
|
||||||
|
function showDeskToolsProcesses(message) {
|
||||||
|
deskTools.msg = message;
|
||||||
|
if (message == null) { QH('DeskToolsProcesses', ''); return; }
|
||||||
|
if (Q('DeskTools').nodeid != message.nodeid) return;
|
||||||
|
var p = [], processes = null;
|
||||||
|
try { processes = JSON.parse(message.value); } catch (e) { }
|
||||||
|
if (processes != null) {
|
||||||
|
for (var pid in processes) { p.push( { p:parseInt(pid), c:processes[pid].cmd, d:processes[pid].cmd.toLowerCase(), u: processes[pid].user } ); }
|
||||||
|
if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
|
||||||
|
var x = '';
|
||||||
|
for (var i in p) { if (p[i].p != 0) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer title="Stop process" onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u?p[i].u:'') + '</div><div>' + p[i].c + '</div></div>'; } }
|
||||||
|
QH('DeskToolsProcesses', x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Toggle mouse and keyboard input
|
// Toggle mouse and keyboard input
|
||||||
function toggleKvmControl() { putstore('DeskControl', (Q("DeskControl").checked?1:0)); }
|
function toggleKvmControl() { putstore('DeskControl', (Q("DeskControl").checked?1:0)); }
|
||||||
|
|
||||||
@ -3393,6 +3449,8 @@
|
|||||||
function dmousemove(e) { if (!xxdialogMode && desktop != null && Q('DeskControl').checked) desktop.m.mousemove(e) }
|
function dmousemove(e) { if (!xxdialogMode && desktop != null && Q('DeskControl').checked) desktop.m.mousemove(e) }
|
||||||
function dmousewheel(e) { if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; }
|
function dmousewheel(e) { if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; }
|
||||||
function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
|
function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
|
||||||
|
function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, 'Stop process #' + id + ' "' + name + '"?', id); }
|
||||||
|
function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type:'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// TERMINAL
|
// TERMINAL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user