mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Many agent & UI improvements
This commit is contained in:
parent
8dcd8938a6
commit
23bc223f18
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
agents/meshagent_osx-x86-64
Normal file
BIN
agents/meshagent_osx-x86-64
Normal file
Binary file not shown.
@ -29,9 +29,12 @@ function createMeshCore(agent) {
|
||||
this.Start = function Start(user) {
|
||||
if (this.container == null) {
|
||||
if (process.platform == 'win32') {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.SessionId });
|
||||
}
|
||||
else {
|
||||
try {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.SessionId });
|
||||
} catch (ex) {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1 });
|
||||
}
|
||||
} else {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.uid });
|
||||
}
|
||||
this.container.parent = this;
|
||||
@ -47,33 +50,21 @@ function createMeshCore(agent) {
|
||||
this._container = this.container;
|
||||
this._container.parent = this;
|
||||
this.container = null;
|
||||
|
||||
this._container.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
obj.borderManager = new borderController();
|
||||
*/
|
||||
|
||||
require('events').EventEmitter.call(obj, true).createEvent('loggedInUsers_Updated');
|
||||
obj.on('loggedInUsers_Updated', function ()
|
||||
{
|
||||
var users = []
|
||||
for(var i = 0; i < obj.loggedInUsers.length; ++i)
|
||||
{
|
||||
users.push((obj.loggedInUsers[i].Domain ? (obj.loggedInUsers[i].Domain + '\\') : '') + obj.loggedInUsers[i].Username);
|
||||
}
|
||||
sendConsoleText('LogOn Status Changed. Active Users => [' + users.join(', ') + ']');
|
||||
});
|
||||
//obj.borderManager = new borderController();
|
||||
|
||||
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
||||
obj.meshCoreInfo = "MeshCore v6";
|
||||
obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
||||
obj.loggedInUsers = [];
|
||||
obj.loggedInUsers = null;
|
||||
|
||||
var meshServerConnectionState = 0;
|
||||
var tunnels = {};
|
||||
var lastSelfInfo = null;
|
||||
var lastMeInfo = null;
|
||||
var lastNetworkInfo = null;
|
||||
var lastPublicLocationInfo = null;
|
||||
var selfInfoUpdateTimer = null;
|
||||
@ -92,10 +83,8 @@ function createMeshCore(agent) {
|
||||
var nextTunnelIndex = 1;
|
||||
|
||||
// Get the operating system description string
|
||||
// *** THIS CAUSES AGENT TO BE UNSTABLE!!!
|
||||
//obj.osDesc = null;
|
||||
//try { require('os').name().then(function (v) { obj.osDesc = v; }); } catch (ex) { }
|
||||
// *** THIS CAUSES AGENT TO BE UNSTABLE!!!
|
||||
var osDesc = null;
|
||||
try { require('os').name().then(function (v) { osDesc = v; if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "coreinfo", "value": obj.meshCoreInfo, "osdesc": osDesc }); } }); } catch (ex) { }
|
||||
|
||||
/*
|
||||
var AMTScanner = require("AMTScanner");
|
||||
@ -128,23 +117,23 @@ function createMeshCore(agent) {
|
||||
var AMTScannerModule = require('amt-scanner');
|
||||
amtscanner = new AMTScannerModule();
|
||||
//amtscanner.on('found', function (data) { if (typeof data != 'string') { data = JSON.stringify(data, null, " "); } sendConsoleText(data); });
|
||||
} catch (e) { amtscanner = null; }
|
||||
} catch (ex) { amtscanner = null; }
|
||||
|
||||
// Try to load up the MEI module
|
||||
try {
|
||||
var amtMeiLib = require('amt-mei');
|
||||
amtMei = new amtMeiLib();
|
||||
amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; sendPeriodicServerUpdate(); });
|
||||
amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; });
|
||||
amtMeiConnected = 2;
|
||||
//amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); });
|
||||
} catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
|
||||
sendPeriodicServerUpdate(1);
|
||||
} catch (ex) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
|
||||
|
||||
// Try to load up the WIFI scanner
|
||||
try {
|
||||
var wifiScannerLib = require('wifi-scanner');
|
||||
wifiScanner = new wifiScannerLib();
|
||||
wifiScanner.on('accessPoint', function (data) { sendConsoleText(JSON.stringify(data)); });
|
||||
} catch (e) { wifiScannerLib = null; wifiScanner = null; }
|
||||
} catch (ex) { wifiScannerLib = null; wifiScanner = null; }
|
||||
|
||||
// If we are running in Duktape, agent will be null
|
||||
if (agent == null) {
|
||||
@ -923,7 +912,7 @@ function createMeshCore(agent) {
|
||||
var response = null;
|
||||
switch (cmd) {
|
||||
case 'help': { // Displays available commands
|
||||
response = 'Available commands: help, info, osinfo, 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, toast, lock, users, sendinfo, sendcaps.';
|
||||
response = 'Available commands: help, info, osinfo, 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, toast, lock, users, sendcaps.';
|
||||
break;
|
||||
}
|
||||
/*
|
||||
@ -947,12 +936,7 @@ function createMeshCore(agent) {
|
||||
*/
|
||||
case 'users':
|
||||
{
|
||||
var retList = [];
|
||||
for(var i = 0; i < obj.loggedInUsers.length; ++i)
|
||||
{
|
||||
retList.push((obj.loggedInUsers[i].Domain ? (obj.loggedInUsers[i].Domain + '\\') : '') + obj.loggedInUsers[i].Username);
|
||||
}
|
||||
response = 'Active Users => [' + retList.join(', ') + ']';
|
||||
if (obj.loggedInUsers == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + obj.loggedInUsers.join(', ') + '.'; }
|
||||
}
|
||||
break;
|
||||
case 'toast': {
|
||||
@ -1038,10 +1022,10 @@ function createMeshCore(agent) {
|
||||
case 'info': { // Return information about the agent and agent core module
|
||||
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
|
||||
if (amtLmsState >= 0) { response += '\r\nBuilt-in LMS: ' + ['Disabled', 'Connecting..', 'Connected'][amtLmsState] + '.'; }
|
||||
//if (obj.osDesc) { response += '\r\nOS: ' + obj.osDesc + '.'; }
|
||||
if (osDesc) { response += '\r\nOS: ' + osDesc + '.'; }
|
||||
response += '\r\nModules: ' + addedModules.join(', ') + '.';
|
||||
response += '\r\nServer Connection: ' + mesh.isControlChannelConnected + ', State: ' + meshServerConnectionState + '.';
|
||||
response += '\r\nLastInfo: ' + lastSelfInfo + '.';
|
||||
response += '\r\lastMeInfo: ' + lastMeInfo + '.';
|
||||
var oldNodeId = db.Get('OldNodeId');
|
||||
if (oldNodeId != null) { response += '\r\nOldNodeID: ' + oldNodeId + '.'; }
|
||||
if (process.platform != 'win32') { response += '\r\nX11 support: ' + require('monitor-info').kvm_x11_support + '.'; }
|
||||
@ -1049,7 +1033,7 @@ function createMeshCore(agent) {
|
||||
}
|
||||
case 'osinfo': { // Return the operating system information
|
||||
var i = 1;
|
||||
if (args['_'].length > 0) { i = parseInt(args['_'][0]); response = 'Calling ' + i + ' times.'; }
|
||||
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
|
||||
for (var j = 0; j < i; j++) {
|
||||
var pr = require('os').name();
|
||||
pr.sessionid = sessionid;
|
||||
@ -1057,30 +1041,24 @@ function createMeshCore(agent) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'selfinfo': { // Return self information block
|
||||
buildSelfInfo(function (info) { sendConsoleText(objToString(info, 0, ' ', true), sessionid); });
|
||||
break;
|
||||
}
|
||||
case 'sendinfo': { // Send our information to the server
|
||||
buildSelfInfo(function (selfInfo) {
|
||||
lastSelfInfo = JSON.stringify(selfInfo);
|
||||
sendConsoleText('Sent: ' + lastSelfInfo);
|
||||
mesh.SendCommand(lastSelfInfo);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'sendcaps': { // Send capability flags to the server
|
||||
if (args['_'].length == 0) {
|
||||
response = 'Proper usage: sendcaps (number)'; // Display correct command usage
|
||||
} else {
|
||||
var flags = 0;
|
||||
response = JSON.stringify(args);
|
||||
flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": parseInt(args['_'][0]) };
|
||||
var flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": parseInt(args['_'][0]) };
|
||||
mesh.SendCommand(flags);
|
||||
response = JSON.stringify(flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'sendosdesc': { // Send OS description
|
||||
var os = osDesc;
|
||||
if (args['_'].length > 0) { os = args['_'][0]; }
|
||||
var flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "osdesc": os };
|
||||
mesh.SendCommand(flags);
|
||||
response = JSON.stringify(flags);
|
||||
break;
|
||||
}
|
||||
case 'args': { // Displays parsed command arguments
|
||||
response = 'args ' + objToString(args, 0, ' ', true);
|
||||
break;
|
||||
@ -1380,29 +1358,20 @@ function createMeshCore(agent) {
|
||||
// Server connected, send mesh core information
|
||||
var oldNodeId = db.Get('OldNodeId');
|
||||
if (oldNodeId != null) { mesh.SendCommand({ action: 'mc1migration', oldnodeid: oldNodeId }); }
|
||||
sendPeriodicServerUpdate(true);
|
||||
//if (selfInfoUpdateTimer == null) { selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 60000); } // Should be a long time, like 20 minutes. For now, 1 minute.
|
||||
}
|
||||
}
|
||||
|
||||
// Build a bunch a self information data that will be sent to the server
|
||||
// We need to do this periodically and if anything changes, send the update to the server.
|
||||
function buildSelfInfo(func) {
|
||||
getAmtInfo(function (meinfo) {
|
||||
// Update the server wtih basic info
|
||||
var r = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": obj.meshCoreCapabilities };
|
||||
try {
|
||||
if (meinfo != null) {
|
||||
var intelamt = {}, p = false;
|
||||
if (meinfo.Versions && meinfo.Versions.AMT) { intelamt.ver = meinfo.Versions.AMT; p = true; }
|
||||
if (meinfo.ProvisioningState) { intelamt.state = meinfo.ProvisioningState; p = true; }
|
||||
if (meinfo.Flags) { intelamt.flags = meinfo.Flags; p = true; }
|
||||
if (meinfo.OsHostname) { intelamt.host = meinfo.OsHostname; p = true; }
|
||||
if (meinfo.UUID) { intelamt.uuid = meinfo.UUID; p = true; }
|
||||
if (p == true) { r.intelamt = intelamt }
|
||||
}
|
||||
} catch (ex) { }
|
||||
func(r);
|
||||
});
|
||||
if (osDesc != null) { r.osdesc = osDesc; }
|
||||
mesh.SendCommand(r);
|
||||
|
||||
// Update list of logged in users
|
||||
if (obj.loggedInUsers != null) { mesh.SendCommand({ "action": "coreinfo", "v": { "users": obj.loggedInUsers } }); }
|
||||
|
||||
// Update the server on more advanced stuff, like Intel ME and Network Settings
|
||||
meInfoStr = null;
|
||||
sendPeriodicServerUpdate();
|
||||
//if (selfInfoUpdateTimer == null) { selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 1200000); } // 20 minutes
|
||||
}
|
||||
}
|
||||
|
||||
// Update the server with the latest network interface information
|
||||
@ -1419,18 +1388,33 @@ function createMeshCore(agent) {
|
||||
}
|
||||
|
||||
// Called periodically to check if we need to send updates to the server
|
||||
function sendPeriodicServerUpdate(force) {
|
||||
if ((amtMeiConnected != 1) || (force == true)) { // If we are pending MEI connection, hold off on updating the server on self-info
|
||||
if (force == true) { lastSelfInfo = null; }
|
||||
// Update the self information data
|
||||
buildSelfInfo(function (selfInfo) {
|
||||
selfInfoStr = JSON.stringify(selfInfo);
|
||||
if (selfInfoStr != lastSelfInfo) { mesh.SendCommand(selfInfo); lastSelfInfo = selfInfoStr; }
|
||||
function sendPeriodicServerUpdate(flags) {
|
||||
if (meshServerConnectionState == 0) return; // Not connected to server, do nothing.
|
||||
if (!flags) { flags = 0xFFFFFFFF; }
|
||||
|
||||
if (flags & 1) {
|
||||
// If we have a connected MEI, get Intel ME information
|
||||
getAmtInfo(function (meinfo) {
|
||||
try {
|
||||
if (meinfo == null) return;
|
||||
var intelamt = {}, p = false;
|
||||
if (meinfo.Versions && meinfo.Versions.AMT) { intelamt.ver = meinfo.Versions.AMT; p = true; }
|
||||
if (meinfo.ProvisioningState) { intelamt.state = meinfo.ProvisioningState; p = true; }
|
||||
if (meinfo.Flags) { intelamt.flags = meinfo.Flags; p = true; }
|
||||
if (meinfo.OsHostname) { intelamt.host = meinfo.OsHostname; p = true; }
|
||||
if (meinfo.UUID) { intelamt.uuid = meinfo.UUID; p = true; }
|
||||
if (p == true) {
|
||||
var meInfoStr = JSON.stringify({ "action": "coreinfo", "value": obj.meshCoreInfo, "intelamt": intelamt });
|
||||
if (meInfoStr != lastMeInfo) { mesh.SendCommand(meInfoStr); lastMeInfo = meInfoStr; }
|
||||
}
|
||||
} catch (ex) { }
|
||||
});
|
||||
}
|
||||
|
||||
// Update network information
|
||||
sendNetworkUpdateNagle(force);
|
||||
if (flags & 2) {
|
||||
// Update network information
|
||||
sendNetworkUpdateNagle(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Get Intel AMT information using MEI
|
||||
@ -1492,25 +1476,23 @@ function createMeshCore(agent) {
|
||||
});
|
||||
} catch (e) { amtLmsState = -1; amtLms = null; }
|
||||
|
||||
// Check if the control channel is connected
|
||||
if (mesh.isControlChannelConnected) { handleServerConnection(1); }
|
||||
|
||||
// Setup logged in user monitoring
|
||||
/*
|
||||
require('user-sessions').on('changed', function onUserSessionChanged()
|
||||
{
|
||||
require('user-sessions').enumerateUsers().then(function (users)
|
||||
{
|
||||
obj.loggedInUsers = users.Active;
|
||||
obj.emit('loggedInUsers_Updated');
|
||||
try {
|
||||
var userSession = require('user-sessions');
|
||||
userSession.on('changed', function onUserSessionChanged() {
|
||||
userSession.enumerateUsers().then(function (users) {
|
||||
var u = [], a = users.Active;
|
||||
for (var i in a) { if (a[i].Domain) { u.push(a[i].Domain + '\\' + a[i].Username); } else { u.push(a[i].Username); } }
|
||||
obj.loggedInUsers = u;
|
||||
if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "coreinfo", "users": u }); }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
require('user-sessions').emit('changed');
|
||||
require('user-sessions').on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); });
|
||||
require('user-sessions').on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); });
|
||||
userSession.emit('changed');
|
||||
//userSession.on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); });
|
||||
//userSession.on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); });
|
||||
} catch (ex) { }
|
||||
*/
|
||||
//console.log('Stopping.');
|
||||
//process.exit();
|
||||
}
|
||||
|
||||
obj.stop = function () {
|
||||
@ -1535,7 +1517,8 @@ function createMeshCore(agent) {
|
||||
// KVM Data Channel
|
||||
//
|
||||
|
||||
obj.setupMeiOsAdmin = function(func, state) {
|
||||
obj.setupMeiOsAdmin = function (func, state) {
|
||||
if ((amtMei == null) || (amtMeiConnected != 2)) { return; } // If there is no MEI, don't bother with this.
|
||||
amtMei.getLocalSystemAccount(function (x) {
|
||||
var transport = require('amt-wsman-duk');
|
||||
var wsman = require('amt-wsman');
|
||||
|
@ -30,7 +30,28 @@ function amt_heci() {
|
||||
this._amt.UnicodeStringLen = 20;
|
||||
|
||||
this._amt.Parent = this;
|
||||
this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); });
|
||||
this._amt.on('error', function _amtOnError(e)
|
||||
{
|
||||
if(this.Parent._rq.isEmpty())
|
||||
{
|
||||
this.Parent.emit('error', e); // No pending requests, so propagate the error up
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is a pending request, so fail the pending request
|
||||
var user = this.Parent._rq.deQueue();
|
||||
var params = user.optional;
|
||||
var callback = user.func;
|
||||
params.unshift({ Status: -1 }); // Relay an error
|
||||
callback.apply(this.Parent, params);
|
||||
|
||||
if(!this.Parent._rq.isEmpty())
|
||||
{
|
||||
// There are still more pending requests, so try to re-helpconnect MEI
|
||||
this.connect(heci.GUIDS.AMT, { noPipeline: 1 });
|
||||
}
|
||||
}
|
||||
});
|
||||
this._amt.on('connect', function _amtOnConnect()
|
||||
{
|
||||
this.on('data', function _amtOnData(chunk)
|
||||
@ -70,7 +91,8 @@ function amt_heci() {
|
||||
return (ret);
|
||||
};
|
||||
|
||||
this.sendCommand = function sendCommand() {
|
||||
this.sendCommand = function sendCommand()
|
||||
{
|
||||
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
|
||||
var args = [];
|
||||
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
|
||||
@ -278,8 +300,16 @@ function amt_heci() {
|
||||
this.getLocalSystemAccount = function getLocalSystemAccount(callback) {
|
||||
var optional = [];
|
||||
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
|
||||
if (header.Data.length == 68) { opt.unshift({ user: trim(header.Data.slice(0, 33).toString()), pass: trim(header.Data.slice(33, 67).toString()), raw: header.Data }); } else { opt.unshift(null); }
|
||||
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt)
|
||||
{
|
||||
if (header.Status == 0 && header.Data.length == 68)
|
||||
{
|
||||
opt.unshift({ user: trim(header.Data.slice(0, 33).toString()), pass: trim(header.Data.slice(33, 67).toString()), raw: header.Data });
|
||||
}
|
||||
else
|
||||
{
|
||||
opt.unshift(null);
|
||||
}
|
||||
fn.apply(this, opt);
|
||||
}, callback, optional);
|
||||
}
|
||||
|
@ -197,11 +197,18 @@ function UserSessions()
|
||||
{
|
||||
this.parent.hwnd = h;
|
||||
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
this.parent._wts.WTSRegisterSessionNotification(this.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
//this.parent._user32.ACDC_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||
//this.parent._user32.BATT_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||
//this.parent._user32.DISP_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0); // Windows 8+ only, THIS WILL BLOCK ON WIN7
|
||||
// We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
|
||||
// from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
|
||||
// on a semaphore for us to return. If we call now, we may deadlock on Windows 7, becuase it will try to notify immediately
|
||||
this.immediate = setImmediate(function (self)
|
||||
{
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||
console.log(self.parent._user32.ACDC_H.Val, self.parent._user32.BATT_H.Val, self.parent._user32.DISP_H.Val);
|
||||
}, this);
|
||||
});
|
||||
this._messagepump.on('message', function (msg)
|
||||
{
|
||||
|
@ -30,7 +30,28 @@ function amt_heci() {
|
||||
this._amt.UnicodeStringLen = 20;
|
||||
|
||||
this._amt.Parent = this;
|
||||
this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); });
|
||||
this._amt.on('error', function _amtOnError(e)
|
||||
{
|
||||
if(this.Parent._rq.isEmpty())
|
||||
{
|
||||
this.Parent.emit('error', e); // No pending requests, so propagate the error up
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is a pending request, so fail the pending request
|
||||
var user = this.Parent._rq.deQueue();
|
||||
var params = user.optional;
|
||||
var callback = user.func;
|
||||
params.unshift({ Status: -1 }); // Relay an error
|
||||
callback.apply(this.Parent, params);
|
||||
|
||||
if(!this.Parent._rq.isEmpty())
|
||||
{
|
||||
// There are still more pending requests, so try to re-helpconnect MEI
|
||||
this.connect(heci.GUIDS.AMT, { noPipeline: 1 });
|
||||
}
|
||||
}
|
||||
});
|
||||
this._amt.on('connect', function _amtOnConnect()
|
||||
{
|
||||
this.on('data', function _amtOnData(chunk)
|
||||
@ -70,7 +91,8 @@ function amt_heci() {
|
||||
return (ret);
|
||||
};
|
||||
|
||||
this.sendCommand = function sendCommand() {
|
||||
this.sendCommand = function sendCommand()
|
||||
{
|
||||
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
|
||||
var args = [];
|
||||
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
|
||||
@ -278,8 +300,16 @@ function amt_heci() {
|
||||
this.getLocalSystemAccount = function getLocalSystemAccount(callback) {
|
||||
var optional = [];
|
||||
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
|
||||
if (header.Data.length == 68) { opt.unshift({ user: trim(header.Data.slice(0, 33).toString()), pass: trim(header.Data.slice(33, 67).toString()), raw: header.Data }); } else { opt.unshift(null); }
|
||||
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt)
|
||||
{
|
||||
if (header.Status == 0 && header.Data.length == 68)
|
||||
{
|
||||
opt.unshift({ user: trim(header.Data.slice(0, 33).toString()), pass: trim(header.Data.slice(33, 67).toString()), raw: header.Data });
|
||||
}
|
||||
else
|
||||
{
|
||||
opt.unshift(null);
|
||||
}
|
||||
fn.apply(this, opt);
|
||||
}, callback, optional);
|
||||
}
|
||||
|
128
agents/modules_meshcore/linux-dbus.js
Normal file
128
agents/modules_meshcore/linux-dbus.js
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
try { Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : undefined); } }); } catch (e) { }
|
||||
|
||||
|
||||
|
||||
function dbus(address, uid)
|
||||
{
|
||||
this._ObjectID = 'linux-dbus';
|
||||
require('events').EventEmitter.call(this, true)
|
||||
.createEvent('signal');
|
||||
Object.defineProperty(this, "uid", { value: uid });
|
||||
this._child = require('child_process').execFile("/bin/sh", ["sh"], { type: require('child_process').SpawnTypes.TERM, uid: uid == null ? -1 : uid });
|
||||
this._child.stdin.write('dbus-monitor --session "type=\'signal\', interface=\'' + address + '\'" | ( while true; do read X; echo "$X"; done )\n');
|
||||
this._child.stdout.dbus = this;
|
||||
this._child.stdout.on('data', function (chunk)
|
||||
{
|
||||
// Parse DBUS Data
|
||||
if (!this.ready) { this.ready = true; return; }
|
||||
|
||||
var lines = [];
|
||||
var tokens = chunk.toString().split('\r\n');
|
||||
for (var i in tokens)
|
||||
{
|
||||
if (tokens[i] == '')
|
||||
{
|
||||
// End of record
|
||||
this.dbus.preParseRecords(lines);
|
||||
lines = [];
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.push(tokens[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.preParseRecords = function (lines)
|
||||
{
|
||||
var record = [];
|
||||
for (var i in lines)
|
||||
{
|
||||
if(lines[i].startsWith('signal '))
|
||||
{
|
||||
if(record.length>0)
|
||||
{
|
||||
this.parseRecords(record);
|
||||
}
|
||||
record = [];
|
||||
}
|
||||
record.push(lines[i]);
|
||||
}
|
||||
if (record.length > 0)
|
||||
{
|
||||
this.parseRecords(record);
|
||||
}
|
||||
}
|
||||
this.parseRecords = function (lines)
|
||||
{
|
||||
if (lines[0].startsWith('signal '))
|
||||
{
|
||||
var signal = {};
|
||||
var sigtokens = lines[0].split(' ');
|
||||
sigtokens.shift();
|
||||
|
||||
for (var i in sigtokens) {
|
||||
var sigitems = sigtokens[i].split('=');
|
||||
if (sigitems.length == 2) {
|
||||
signal[sigitems[0]] = sigitems[1];
|
||||
}
|
||||
}
|
||||
|
||||
lines.shift();
|
||||
signal.data = lines;
|
||||
|
||||
this.parseSignal(signal);
|
||||
}
|
||||
}
|
||||
this.parseSignal = function(signal)
|
||||
{
|
||||
var data = signal.data;
|
||||
signal.data = [];
|
||||
|
||||
for(var i=0; i<data.length; ++i)
|
||||
{
|
||||
if (data[i].startsWith('array '))
|
||||
{
|
||||
signal.data.push([]);
|
||||
for(i=i+1; i<data.length; ++i)
|
||||
{
|
||||
this.parseSignal2(data[i], signal.data.peek());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parseSignal2(data[i], signal.data);
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('signal', signal);
|
||||
}
|
||||
this.parseSignal2 = function (inputStr, outArray)
|
||||
{
|
||||
if(inputStr.startsWith('string '))
|
||||
{
|
||||
outArray.push(JSON.parse(inputStr.slice(7)));
|
||||
}
|
||||
else if(inputStr.startsWith('boolean '))
|
||||
{
|
||||
outArray.push(JSON.parse(inputStr.slice(8)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = dbus;
|
@ -197,11 +197,18 @@ function UserSessions()
|
||||
{
|
||||
this.parent.hwnd = h;
|
||||
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
this.parent._wts.WTSRegisterSessionNotification(this.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
//this.parent._user32.ACDC_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||
//this.parent._user32.BATT_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||
//this.parent._user32.DISP_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0); // Windows 8+ only, THIS WILL BLOCK ON WIN7
|
||||
// We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
|
||||
// from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
|
||||
// on a semaphore for us to return. If we call now, we may deadlock on Windows 7, becuase it will try to notify immediately
|
||||
this.immediate = setImmediate(function (self)
|
||||
{
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||
console.log(self.parent._user32.ACDC_H.Val, self.parent._user32.BATT_H.Val, self.parent._user32.DISP_H.Val);
|
||||
}, this);
|
||||
});
|
||||
this._messagepump.on('message', function (msg)
|
||||
{
|
||||
|
34
meshagent.js
34
meshagent.js
@ -89,7 +89,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
if (msg.length < 2) return;
|
||||
var cmdid = obj.common.ReadShort(msg, 0);
|
||||
if (cmdid == 11) { // MeshCommand_CoreModuleHash
|
||||
if (msg.length == 4) { ChangeAgentCoreInfo({ caps: 0 }); } // If the agent indicated that no core is running, clear the core information string.
|
||||
if (msg.length == 4) { ChangeAgentCoreInfo({ "caps": 0 }); } // If the agent indicated that no core is running, clear the core information string.
|
||||
// Mesh core hash, sent by agent with the hash of the current mesh core.
|
||||
if (obj.agentCoreCheck == 1000) return; // If we are using a custom core, don't try to update it.
|
||||
// We need to check if the core is current.
|
||||
@ -552,7 +552,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
var node = nodes[0];
|
||||
if (node.meshid == obj.dbMeshKey) {
|
||||
// Update the device name & host
|
||||
var newNode = { name: node.name };
|
||||
var newNode = { "name": node.name };
|
||||
if (node.intelamt != null) { newNode.intelamt = node.intelamt; }
|
||||
ChangeAgentCoreInfo(newNode);
|
||||
|
||||
@ -575,9 +575,6 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
function ChangeAgentCoreInfo(command) {
|
||||
if ((command == null) || (command == null)) return; // Safety, should never happen.
|
||||
|
||||
// Check capabilities value
|
||||
if (command.caps == null || command.caps == null) { command.caps = 0; } else { if (typeof command.caps != 'number') command.caps = 0; }
|
||||
|
||||
// Check that the mesh exists
|
||||
var mesh = obj.parent.meshes[obj.dbMeshKey];
|
||||
if (mesh == null) return;
|
||||
@ -589,30 +586,39 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
if (device.agent) {
|
||||
var changes = [], change = 0;
|
||||
|
||||
//if (command.users) { console.log(command.users); }
|
||||
|
||||
// Check if anything changes
|
||||
if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); }
|
||||
if (device.agent.core != command.value) { if ((command.value == null) && (device.agent.core != null)) { delete device.agent.core; } else { device.agent.core = command.value; } change = 1; changes.push('agent core'); }
|
||||
if ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7)) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; changes.push('agent capabilities'); } // Allow Javascript on the agent to change all capabilities except console and javascript support
|
||||
if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; changes.push('agent capabilities'); } // Allow Javascript on the agent to change all capabilities except console and javascript support
|
||||
if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; changes.push('os desc'); }
|
||||
if (command.intelamt) {
|
||||
if (!device.intelamt) { device.intelamt = {}; }
|
||||
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { device.intelamt.ver = command.intelamt.ver; change = 1; changes.push('AMT version'); }
|
||||
if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); }
|
||||
if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); }
|
||||
if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { device.intelamt.host = command.intelamt.host; change = 1; changes.push('AMT host'); }
|
||||
if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); }
|
||||
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; }
|
||||
if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { changes.push('AMT state'); device.intelamt.state = command.intelamt.state; change = 1; }
|
||||
if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) {
|
||||
if (device.intelamt.flags) { changes.push('AMT flags (' + device.intelamt.flags + ' --> ' + command.intelamt.flags + ')'); } else { changes.push('AMT flags (' + command.intelamt.flags + ')'); }
|
||||
device.intelamt.flags = command.intelamt.flags; change = 1;
|
||||
}
|
||||
if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { changes.push('AMT host'); device.intelamt.host = command.intelamt.host; change = 1; }
|
||||
if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { changes.push('AMT uuid'); device.intelamt.uuid = command.intelamt.uuid; change = 1; }
|
||||
}
|
||||
if ((command.users != null) && (device.users != command.users)) { device.users = command.users; change = 1; } // Would be nice not to save this to the db.
|
||||
if (mesh.mtype == 2) {
|
||||
if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); }
|
||||
// TODO: Check that the agent has an interface that is the same as the one we got this websocket connection on. Only set if we have a match.
|
||||
}
|
||||
|
||||
// If there are changes, save and event
|
||||
// If there are changes, event the new device
|
||||
if (change == 1) {
|
||||
// Save to the database
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the node change
|
||||
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') };
|
||||
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
|
||||
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id };
|
||||
if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); }
|
||||
if ((obj.agentInfo.capabilities & 0x20) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes
|
||||
var device2 = obj.common.Clone(device);
|
||||
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
|
||||
event.node = device;
|
||||
|
@ -946,12 +946,12 @@ function CreateMeshCentralServer(config, args) {
|
||||
8: { id: 8, localname: 'MeshAgent-Linux-XEN-x86-32', rname: 'meshagent', desc: 'XEN x86-64', update: true, amt: false, platform: 'linux' },
|
||||
9: { id: 9, localname: 'meshagent_arm', rname: 'meshagent', desc: 'Linux ARM5', update: true, amt: false, platform: 'linux' },
|
||||
10: { id: 10, localname: 'MeshAgent-Linux-ARM-PlugPC', rname: 'meshagent', desc: 'Linux ARM PlugPC', update: true, amt: false, platform: 'linux' },
|
||||
11: { id: 11, localname: 'MeshAgent-OSX-x86-32', rname: 'meshosx', desc: 'Apple OSX x86-32', update: true, amt: false, platform: 'linux' },
|
||||
11: { id: 11, localname: 'meshagent_osx-x86-32', rname: 'meshosx', desc: 'Apple OSX x86-32', update: true, amt: false, platform: 'linux' },
|
||||
12: { id: 12, localname: 'MeshAgent-Android-x86', rname: 'meshandroid', desc: 'Android x86-32', update: true, amt: false, platform: 'linux' },
|
||||
13: { id: 13, localname: 'meshagent_pogo', rname: 'meshagent', desc: 'Linux ARM PogoPlug', update: true, amt: false, platform: 'linux' },
|
||||
14: { id: 14, localname: 'MeshAgent-Android-APK', rname: 'meshandroid', desc: 'Android Market', update: false, amt: false, platform: 'android' }, // Get this one from Google Play
|
||||
15: { id: 15, localname: 'meshagent_poky', rname: 'meshagent', desc: 'Linux Poky x86-32', update: true, amt: false, platform: 'linux' },
|
||||
16: { id: 16, localname: 'MeshAgent-OSX-x86-64', rname: 'meshagent', desc: 'Apple OSX x86-64', update: true, amt: false, platform: 'osx' },
|
||||
16: { id: 16, localname: 'meshagent_osx-x86-64', rname: 'meshagent', desc: 'Apple OSX x86-64', update: true, amt: false, platform: 'osx' },
|
||||
17: { id: 17, localname: 'MeshAgent-ChromeOS', rname: 'meshagent', desc: 'Google ChromeOS', update: false, amt: false, platform: 'chromeos' }, // Get this one from Chrome store
|
||||
18: { id: 18, localname: 'meshagent_poky64', rname: 'meshagent', desc: 'Linux Poky x86-64', update: true, amt: false, platform: 'linux' },
|
||||
19: { id: 19, localname: 'meshagent_x86_nokvm', rname: 'meshagent', desc: 'Linux x86-32 NoKVM', update: true, amt: true, platform: 'linux' },
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.2.0-w",
|
||||
"version": "0.2.0-y",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
@ -39,6 +39,14 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.noMouseRotate = false;
|
||||
obj.rotation = 0;
|
||||
// ###END###{DesktopRotation}
|
||||
// ###BEGIN###{DesktopInband}
|
||||
obj.kvmDataSupported = false;
|
||||
obj.onKvmData = null;
|
||||
obj.onKvmDataPending = [];
|
||||
obj.onKvmDataAck = -1;
|
||||
obj.holding = false;
|
||||
obj.lastKeepAlive = Date.now();
|
||||
// ###END###{DesktopInband}
|
||||
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
obj.mx = 0; // Last mouse x position
|
||||
@ -138,6 +146,9 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
var supportedEncodings = '';
|
||||
if (obj.useZRLE) supportedEncodings += IntToStr(16);
|
||||
supportedEncodings += IntToStr(0);
|
||||
// ###BEGIN###{DesktopInband}
|
||||
supportedEncodings += IntToStr(1092);
|
||||
// ###END###{DesktopInband}
|
||||
|
||||
obj.send(String.fromCharCode(2, 0) + ShortToStr((supportedEncodings.length / 4) + 1) + supportedEncodings + IntToStr(-223)); // Supported Encodings + Desktop Size
|
||||
|
||||
@ -157,13 +168,21 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); }
|
||||
}
|
||||
else if (obj.state == 4) {
|
||||
var c = obj.acc.charCodeAt(0);
|
||||
if (c == 2) {
|
||||
cmdsize = 1; // This is the bell, do nothing.
|
||||
} else if (c == 0) {
|
||||
if (obj.acc.length < 4) return;
|
||||
obj.state = 100 + ReadShort(obj.acc, 2); // Read the number of tiles that are going to be sent, add 100 and use that as our protocol state.
|
||||
cmdsize = 4;
|
||||
switch (obj.acc.charCodeAt(0)) {
|
||||
case 0: // FramebufferUpdate
|
||||
if (obj.acc.length < 4) return;
|
||||
obj.state = 100 + ReadShort(obj.acc, 2); // Read the number of tiles that are going to be sent, add 100 and use that as our protocol state.
|
||||
cmdsize = 4;
|
||||
break;
|
||||
case 2: // This is the bell, do nothing.
|
||||
cmdsize = 1;
|
||||
break;
|
||||
case 3: // This is ServerCutText
|
||||
if (obj.acc.length < 8) return;
|
||||
var len = ReadInt(obj.acc, 4) + 8;
|
||||
if (obj.acc.length < len) return;
|
||||
cmdsize = handleServerCutText(obj.acc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (obj.state > 100 && obj.acc.length >= 12) {
|
||||
@ -319,7 +338,31 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
}
|
||||
}
|
||||
|
||||
// ###BEGIN###{DesktopInband}
|
||||
obj.hold = function (holding) {
|
||||
if (obj.holding == holding) return;
|
||||
obj.holding = holding;
|
||||
obj.canvas.fillStyle = '#000000';
|
||||
obj.canvas.fillRect(0, 0, obj.width, obj.height); // Paint black
|
||||
if (obj.holding == false) {
|
||||
// Go back to normal operations
|
||||
// Set canvas size and ask for full screen refresh
|
||||
if ((obj.canvas.canvas.width != obj.width) || (obj.canvas.canvas.height != obj.height)) {
|
||||
obj.canvas.canvas.width = obj.width; obj.canvas.canvas.height = obj.height;
|
||||
if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); } // ???
|
||||
}
|
||||
obj.Send(String.fromCharCode(3, 0, 0, 0, 0, 0) + ShortToStr(obj.width) + ShortToStr(obj.height)); // FramebufferUpdateRequest
|
||||
} else {
|
||||
obj.UnGrabMouseInput();
|
||||
obj.UnGrabKeyInput();
|
||||
}
|
||||
}
|
||||
// ###END###{DesktopInband}
|
||||
|
||||
function _putImage(i, x, y) {
|
||||
// ###BEGIN###{DesktopInband}
|
||||
if (obj.holding == true) return;
|
||||
// ###END###{DesktopInband}
|
||||
// ###BEGIN###{DesktopRotation}
|
||||
var xx = _arotX(x, y);
|
||||
y = _arotY(x, y);
|
||||
@ -416,6 +459,11 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.setRotation = function (x) {
|
||||
while (x < 0) { x += 4; }
|
||||
var newrotation = x % 4;
|
||||
//console.log('hard-rot: ' + newrotation);
|
||||
// ###BEGIN###{DesktopInband}
|
||||
if (obj.holding == true) { obj.rotation = newrotation; return; }
|
||||
// ###END###{DesktopInband}
|
||||
|
||||
if (newrotation == obj.rotation) return true;
|
||||
var rw = obj.canvas.canvas.width;
|
||||
var rh = obj.canvas.canvas.height;
|
||||
@ -451,6 +499,9 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
function _fixColor(c) { return (c > 127) ? (c + 32) : c; }
|
||||
|
||||
function _SendRefresh() {
|
||||
// ###BEGIN###{DesktopInband}
|
||||
if (obj.holding == true) return;
|
||||
// ###END###{DesktopInband}
|
||||
// ###BEGIN###{DesktopFocus}
|
||||
if (obj.focusmode > 0) {
|
||||
// Request only pixels around the last mouse position
|
||||
@ -477,6 +528,11 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
// ###BEGIN###{Inflate}
|
||||
obj.inflate.inflateReset();
|
||||
// ###END###{Inflate}
|
||||
// ###BEGIN###{DesktopInband}
|
||||
obj.onKvmDataPending = [];
|
||||
obj.onKvmDataAck = -1;
|
||||
obj.kvmDataSupported = false;
|
||||
// ###END###{DesktopInband}
|
||||
for (var i in obj.sparecache) { delete obj.sparecache[i]; }
|
||||
}
|
||||
|
||||
@ -555,6 +611,43 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
else { obj.send(String.fromCharCode(4, d, 0, 0) + IntToStr(k)); }
|
||||
}
|
||||
|
||||
function handleServerCutText(acc) {
|
||||
if (acc.length < 8) return 0;
|
||||
var len = ReadInt(obj.acc, 4) + 8;
|
||||
if (acc.length < len) return 0;
|
||||
// ###BEGIN###{DesktopInband}
|
||||
if (obj.onKvmData != null) {
|
||||
var d = acc.substring(8, len);
|
||||
if ((d.length >= 16) && (d.substring(0, 15) == '\0KvmDataChannel')) {
|
||||
if (obj.kvmDataSupported == false) { obj.kvmDataSupported = true; console.log('KVM Data Channel Supported.'); }
|
||||
if (((obj.onKvmDataAck == -1) && (d.length == 16)) || (d.charCodeAt(15) != 0)) { obj.onKvmDataAck = true; }
|
||||
//if (urlvars && urlvars['kvmdatatrace']) { console.log('KVM-Recv(' + (d.length - 16) + '): ' + d.substring(16)); }
|
||||
if (d.length > 16) { obj.onKvmData(d.substring(16)); } // Event the data and ack
|
||||
if ((obj.onKvmDataAck == true) && (obj.onKvmDataPending.length > 0)) { obj.sendKvmData(obj.onKvmDataPending.shift()); } // Send pending data
|
||||
}
|
||||
}
|
||||
// ###END###{DesktopInband}
|
||||
return len;
|
||||
}
|
||||
|
||||
// ###BEGIN###{DesktopInband}
|
||||
obj.sendKvmData = function (x) {
|
||||
if (obj.onKvmDataAck !== true) {
|
||||
obj.onKvmDataPending.push(x);
|
||||
} else {
|
||||
if (urlvars && urlvars['kvmdatatrace']) { console.log('KVM-Send(' + x.length + '): ' + x); }
|
||||
x = '\0KvmDataChannel\0' + x;
|
||||
obj.Send(String.fromCharCode(6, 0, 0, 0) + IntToStr(x.length) + x);
|
||||
obj.onKvmDataAck = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Send a HWKVM keep alive if it's not been sent in the last 5 seconds.
|
||||
obj.sendKeepAlive = function () {
|
||||
if (obj.lastKeepAlive < Date.now() - 5000) { obj.lastKeepAlive = Date.now(); obj.Send(String.fromCharCode(6, 0, 0, 0) + IntToStr(16) + '\0KvmDataChannel\0'); }
|
||||
}
|
||||
// ###END###{DesktopInband}
|
||||
|
||||
obj.SendCtrlAltDelMsg = function () { obj.sendcad(); }
|
||||
obj.sendcad = function () { obj.sendkey([[0xFFE3, 1], [0xFFE9, 1], [0xFFFF, 1], [0xFFFF, 0], [0xFFE9, 0], [0xFFE3, 0]]); } // Control down, Alt down, Delete down, Delete up , Alt up , Control up
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -144,8 +144,8 @@
|
||||
</div>
|
||||
<div id=p1 style=display:none>
|
||||
<div style="float:right" id="devListToolbarViewIcons">
|
||||
<div id=devViewButton1 class="viewSelector" onclick=onDeviceViewChange(1) title="Columns"><div class="viewSelector1"></div></div>
|
||||
<div id=devViewButton2 class=viewSelector onclick=onDeviceViewChange(2) title="List"><div class="viewSelector2"></div></div>
|
||||
<div id=devViewButton1 class="viewSelector" onclick=onDeviceViewChange(1) title="Columns"><div class="viewSelector2"></div></div>
|
||||
<div id=devViewButton2 class=viewSelector onclick=onDeviceViewChange(2) title="List"><div class="viewSelector1"></div></div>
|
||||
<div id=devViewButton3 class=viewSelector onclick=onDeviceViewChange(3) title="Desktops"><div class="viewSelector3"></div></div>
|
||||
<div id=devViewButton4 class=viewSelector onclick=onDeviceViewChange(4) title="Map"><div class="viewSelector4"></div></div>
|
||||
</div><div><h1>My Devices</h1></div>
|
||||
@ -1361,12 +1361,15 @@
|
||||
for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
|
||||
if (index != -1) {
|
||||
var node = nodes[index];
|
||||
console.log(node);
|
||||
|
||||
// Change the node
|
||||
node.name = message.event.node.name;
|
||||
node.rname = message.event.node.rname;
|
||||
node.users = message.event.node.users;
|
||||
node.host = message.event.node.host;
|
||||
node.desc = message.event.node.desc;
|
||||
node.osdesc = message.event.node.osdesc;
|
||||
node.publicip = message.event.node.publicip;
|
||||
node.iploc = message.event.node.iploc;
|
||||
node.wifiloc = message.event.node.wifiloc;
|
||||
@ -1892,6 +1895,7 @@
|
||||
desk.m.bpp = 1;
|
||||
desk.m.useZRLE = true;
|
||||
desk.m.showmouse = true;
|
||||
desk.m.onKvmData = function (data) { console.log('KVMData: ' + data); };
|
||||
//desk.m.onScreenSizeChange = deskAdjust;
|
||||
desk.Start(nodeid, 16994, '*', '*', 0);
|
||||
desk.contype = 2;
|
||||
@ -2075,8 +2079,8 @@
|
||||
function addAgentToMesh(meshid) {
|
||||
if (xxdialogMode) return;
|
||||
var mesh = meshes[meshid], x = '';
|
||||
//x += addHtmlValue('Operating System', '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>Windows</option><option value=1>Linux</option><option value=2>Apple OSX</option><option value=3>Windows (UnInstall)</option><option value=4>Linux (UnInstall)</option></select>') + '<hr>';
|
||||
x += addHtmlValue('Operating System', '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>Windows</option><option value=1>Linux</option><option value=3>Windows (UnInstall)</option><option value=4>Linux (UnInstall)</option></select>') + '<hr>';
|
||||
x += addHtmlValue('Operating System', '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>Windows</option><option value=1>Linux</option><option value=2>Apple OSX</option><option value=3>Windows (UnInstall)</option><option value=4>Linux (UnInstall)</option></select>') + '<hr>';
|
||||
//x += addHtmlValue('Operating System', '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>Windows</option><option value=1>Linux</option><option value=3>Windows (UnInstall)</option><option value=4>Linux (UnInstall)</option></select>') + '<hr>';
|
||||
|
||||
// Windows agent install
|
||||
//x += "<div id=agins_windows>To add a new computer to mesh " + EscapeHtml(mesh.name) + ", download the mesh agent and configuration file and install the agent on the computer to manage.<br /><br />";
|
||||
@ -2093,7 +2097,7 @@
|
||||
|
||||
// OSX agent install
|
||||
x += "<div id=agins_osx style=display:none>To add a new computer to mesh " + EscapeHtml(mesh.name) + ", download the mesh agent and install it the computer to manage. This agent installer has server and mesh information embedded within it.<br /><br />";
|
||||
x += addHtmlValue('Mesh Agent', '<a href="meshosxagent?id=3&meshid=' + meshid.split('/')[2] + '" target="_blank" title="64bit version of OSX Mesh Agent">OSX Agent (64bit)</a>');
|
||||
x += addHtmlValue('Mesh Agent', '<a href="meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '" target="_blank" title="64bit version of OSX Mesh Agent">OSX Agent (64bit) - TEST BUILD</a>');
|
||||
x += "</div>";
|
||||
|
||||
// Windows agent uninstall
|
||||
@ -3067,6 +3071,12 @@
|
||||
// Attribute: Intel AMT
|
||||
//if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel® AMT', node.intelamt.user); }
|
||||
|
||||
// Operating system description
|
||||
if (node.osdesc) { x += addDeviceAttribute('Operating System', node.osdesc); }
|
||||
|
||||
// Active Users
|
||||
if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute('Active User' + ((node.users.length > 1)?'s':''), node.users.join(', ')); }
|
||||
|
||||
// Attribute: Connectivity (Only show this if more than just the agent is connected).
|
||||
var connectivity = node.conn;
|
||||
if (connectivity && connectivity > 1) {
|
||||
@ -3583,6 +3593,7 @@
|
||||
desktop.m.useZRLE = (desktopsettings.encoding < 3);
|
||||
desktop.m.showmouse = desktopsettings.showmouse;
|
||||
desktop.m.onScreenSizeChange = deskAdjust;
|
||||
desktop.m.onKvmData = function (data) { console.log('KVMData: ' + data); };
|
||||
desktop.Start(desktopNode._id, 16994, '*', '*', 0);
|
||||
desktop.contype = 2;
|
||||
} else {
|
||||
|
@ -1636,11 +1636,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if ((domain == null) || (req.query.id == null)) { res.sendStatus(404); return; }
|
||||
|
||||
// If required, check if this user has rights to do this
|
||||
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true) && (req.session.userid == null)) { res.sendStatus(401); console.log('2'); return; }
|
||||
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true) && (req.session.userid == null)) { res.sendStatus(401); return; }
|
||||
|
||||
// Send a specific mesh agent back
|
||||
var argentInfo = obj.parent.meshAgentBinaries[req.query.id];
|
||||
if ((argentInfo == null) || (req.query.meshid == null)) { res.sendStatus(404); console.log('3'); return; }
|
||||
if ((argentInfo == null) || (req.query.meshid == null)) { res.sendStatus(404); return; }
|
||||
|
||||
// We are going to embed the .msh file into the Windows executable (signed or not).
|
||||
// First, fetch the mesh object to build the .msh file
|
||||
@ -1651,8 +1651,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
|
||||
var user = obj.users[req.session.userid];
|
||||
var escUserId = obj.common.escapeFieldName(user._id);
|
||||
if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); console.log('4'); return; }
|
||||
if (domain.id != mesh.domain) { res.sendStatus(401); console.log('5'); return; }
|
||||
if ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
|
||||
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
|
||||
}
|
||||
|
||||
var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
|
Loading…
Reference in New Issue
Block a user