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

Many agent & UI improvements

This commit is contained in:
Ylian Saint-Hilaire 2018-09-21 16:34:35 -07:00
parent 8dcd8938a6
commit 23bc223f18
21 changed files with 450 additions and 155 deletions

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

Binary file not shown.

View file

@ -29,9 +29,12 @@ function createMeshCore(agent) {
this.Start = function Start(user) { this.Start = function Start(user) {
if (this.container == null) { if (this.container == null) {
if (process.platform == 'win32') { if (process.platform == 'win32') {
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.SessionId }); try {
} this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.SessionId });
else { } catch (ex) {
this.container = require('ScriptContainer').Create({ processIsolation: 1 });
}
} else {
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.uid }); this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.uid });
} }
this.container.parent = this; this.container.parent = this;
@ -47,33 +50,21 @@ function createMeshCore(agent) {
this._container = this.container; this._container = this.container;
this._container.parent = this; this._container.parent = this;
this.container = null; this.container = null;
this._container.exit(); 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. // MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
obj.meshCoreInfo = "MeshCore v6"; obj.meshCoreInfo = "MeshCore v6";
obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
obj.loggedInUsers = []; obj.loggedInUsers = null;
var meshServerConnectionState = 0; var meshServerConnectionState = 0;
var tunnels = {}; var tunnels = {};
var lastSelfInfo = null; var lastMeInfo = null;
var lastNetworkInfo = null; var lastNetworkInfo = null;
var lastPublicLocationInfo = null; var lastPublicLocationInfo = null;
var selfInfoUpdateTimer = null; var selfInfoUpdateTimer = null;
@ -92,10 +83,8 @@ function createMeshCore(agent) {
var nextTunnelIndex = 1; var nextTunnelIndex = 1;
// Get the operating system description string // Get the operating system description string
// *** THIS CAUSES AGENT TO BE UNSTABLE!!! var osDesc = null;
//obj.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) { }
//try { require('os').name().then(function (v) { obj.osDesc = v; }); } catch (ex) { }
// *** THIS CAUSES AGENT TO BE UNSTABLE!!!
/* /*
var AMTScanner = require("AMTScanner"); var AMTScanner = require("AMTScanner");
@ -128,23 +117,23 @@ function createMeshCore(agent) {
var AMTScannerModule = require('amt-scanner'); var AMTScannerModule = require('amt-scanner');
amtscanner = new AMTScannerModule(); amtscanner = new AMTScannerModule();
//amtscanner.on('found', function (data) { if (typeof data != 'string') { data = JSON.stringify(data, null, " "); } sendConsoleText(data); }); //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 to load up the MEI module
try { try {
var amtMeiLib = require('amt-mei'); var amtMeiLib = require('amt-mei');
amtMei = new amtMeiLib(); 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; amtMeiConnected = 2;
//amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); }); sendPeriodicServerUpdate(1);
} catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; } } catch (ex) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
// Try to load up the WIFI scanner // Try to load up the WIFI scanner
try { try {
var wifiScannerLib = require('wifi-scanner'); var wifiScannerLib = require('wifi-scanner');
wifiScanner = new wifiScannerLib(); wifiScanner = new wifiScannerLib();
wifiScanner.on('accessPoint', function (data) { sendConsoleText(JSON.stringify(data)); }); 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 we are running in Duktape, agent will be null
if (agent == null) { if (agent == null) {
@ -923,7 +912,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, 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; break;
} }
/* /*
@ -947,12 +936,7 @@ function createMeshCore(agent) {
*/ */
case 'users': case 'users':
{ {
var retList = []; if (obj.loggedInUsers == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + obj.loggedInUsers.join(', ') + '.'; }
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(', ') + ']';
} }
break; break;
case 'toast': { case 'toast': {
@ -1038,10 +1022,10 @@ function createMeshCore(agent) {
case 'info': { // Return information about the agent and agent core module 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 + '.'; 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 (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\nModules: ' + addedModules.join(', ') + '.';
response += '\r\nServer Connection: ' + mesh.isControlChannelConnected + ', State: ' + meshServerConnectionState + '.'; response += '\r\nServer Connection: ' + mesh.isControlChannelConnected + ', State: ' + meshServerConnectionState + '.';
response += '\r\nLastInfo: ' + lastSelfInfo + '.'; response += '\r\lastMeInfo: ' + lastMeInfo + '.';
var oldNodeId = db.Get('OldNodeId'); var oldNodeId = db.Get('OldNodeId');
if (oldNodeId != null) { response += '\r\nOldNodeID: ' + oldNodeId + '.'; } if (oldNodeId != null) { response += '\r\nOldNodeID: ' + oldNodeId + '.'; }
if (process.platform != 'win32') { response += '\r\nX11 support: ' + require('monitor-info').kvm_x11_support + '.'; } 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 case 'osinfo': { // Return the operating system information
var i = 1; 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++) { for (var j = 0; j < i; j++) {
var pr = require('os').name(); var pr = require('os').name();
pr.sessionid = sessionid; pr.sessionid = sessionid;
@ -1057,30 +1041,24 @@ function createMeshCore(agent) {
} }
break; 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 case 'sendcaps': { // Send capability flags to the server
if (args['_'].length == 0) { if (args['_'].length == 0) {
response = 'Proper usage: sendcaps (number)'; // Display correct command usage response = 'Proper usage: sendcaps (number)'; // Display correct command usage
} else { } else {
var flags = 0; var flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": parseInt(args['_'][0]) };
response = JSON.stringify(args);
flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": parseInt(args['_'][0]) };
mesh.SendCommand(flags); mesh.SendCommand(flags);
response = JSON.stringify(flags); response = JSON.stringify(flags);
} }
break; 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 case 'args': { // Displays parsed command arguments
response = 'args ' + objToString(args, 0, ' ', true); response = 'args ' + objToString(args, 0, ' ', true);
break; break;
@ -1380,31 +1358,22 @@ function createMeshCore(agent) {
// Server connected, send mesh core information // Server connected, send mesh core information
var oldNodeId = db.Get('OldNodeId'); var oldNodeId = db.Get('OldNodeId');
if (oldNodeId != null) { mesh.SendCommand({ action: 'mc1migration', oldnodeid: 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. // Update the server wtih basic info
var r = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": obj.meshCoreCapabilities };
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
} }
} }
// 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) {
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);
});
}
// Update the server with the latest network interface information // Update the server with the latest network interface information
var sendNetworkUpdateNagleTimer = null; var sendNetworkUpdateNagleTimer = null;
function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { clearTimeout(sendNetworkUpdateNagleTimer); sendNetworkUpdateNagleTimer = null; } sendNetworkUpdateNagleTimer = setTimeout(sendNetworkUpdate, 5000); } function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { clearTimeout(sendNetworkUpdateNagleTimer); sendNetworkUpdateNagleTimer = null; } sendNetworkUpdateNagleTimer = setTimeout(sendNetworkUpdate, 5000); }
@ -1419,18 +1388,33 @@ function createMeshCore(agent) {
} }
// Called periodically to check if we need to send updates to the server // Called periodically to check if we need to send updates to the server
function sendPeriodicServerUpdate(force) { function sendPeriodicServerUpdate(flags) {
if ((amtMeiConnected != 1) || (force == true)) { // If we are pending MEI connection, hold off on updating the server on self-info if (meshServerConnectionState == 0) return; // Not connected to server, do nothing.
if (force == true) { lastSelfInfo = null; } if (!flags) { flags = 0xFFFFFFFF; }
// Update the self information data
buildSelfInfo(function (selfInfo) { if (flags & 1) {
selfInfoStr = JSON.stringify(selfInfo); // If we have a connected MEI, get Intel ME information
if (selfInfoStr != lastSelfInfo) { mesh.SendCommand(selfInfo); lastSelfInfo = selfInfoStr; } 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 if (flags & 2) {
sendNetworkUpdateNagle(force); // Update network information
sendNetworkUpdateNagle(false);
}
} }
// Get Intel AMT information using MEI // Get Intel AMT information using MEI
@ -1492,25 +1476,23 @@ function createMeshCore(agent) {
}); });
} catch (e) { amtLmsState = -1; amtLms = null; } } catch (e) { amtLmsState = -1; amtLms = null; }
// Check if the control channel is connected // Setup logged in user monitoring
if (mesh.isControlChannelConnected) { handleServerConnection(1); }
/* /*
require('user-sessions').on('changed', function onUserSessionChanged() try {
{ var userSession = require('user-sessions');
require('user-sessions').enumerateUsers().then(function (users) userSession.on('changed', function onUserSessionChanged() {
{ userSession.enumerateUsers().then(function (users) {
obj.loggedInUsers = users.Active; var u = [], a = users.Active;
obj.emit('loggedInUsers_Updated'); 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 }); }
});
}); });
}); userSession.emit('changed');
//userSession.on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); });
require('user-sessions').emit('changed'); //userSession.on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); });
require('user-sessions').on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); }); } catch (ex) { }
require('user-sessions').on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); });
*/ */
//console.log('Stopping.');
//process.exit();
} }
obj.stop = function () { obj.stop = function () {
@ -1535,7 +1517,8 @@ function createMeshCore(agent) {
// KVM Data Channel // 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) { amtMei.getLocalSystemAccount(function (x) {
var transport = require('amt-wsman-duk'); var transport = require('amt-wsman-duk');
var wsman = require('amt-wsman'); var wsman = require('amt-wsman');

View file

@ -30,7 +30,28 @@ function amt_heci() {
this._amt.UnicodeStringLen = 20; this._amt.UnicodeStringLen = 20;
this._amt.Parent = this; 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._amt.on('connect', function _amtOnConnect()
{ {
this.on('data', function _amtOnData(chunk) this.on('data', function _amtOnData(chunk)
@ -70,7 +91,8 @@ function amt_heci() {
return (ret); 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'); } if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
var args = []; var args = [];
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); } for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
@ -278,8 +300,16 @@ function amt_heci() {
this.getLocalSystemAccount = function getLocalSystemAccount(callback) { this.getLocalSystemAccount = function getLocalSystemAccount(callback) {
var optional = []; var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); } for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) { 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); } {
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); fn.apply(this, opt);
}, callback, optional); }, callback, optional);
} }

View file

@ -197,11 +197,18 @@ function UserSessions()
{ {
this.parent.hwnd = h; this.parent.hwnd = h;
// Now that we have a window handle, we can register it to receive Windows Messages // We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
this.parent._wts.WTSRegisterSessionNotification(this.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS); // from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
//this.parent._user32.ACDC_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0); // 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.parent._user32.BATT_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0); this.immediate = setImmediate(function (self)
//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 {
// 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) this._messagepump.on('message', function (msg)
{ {

View file

@ -30,7 +30,28 @@ function amt_heci() {
this._amt.UnicodeStringLen = 20; this._amt.UnicodeStringLen = 20;
this._amt.Parent = this; 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._amt.on('connect', function _amtOnConnect()
{ {
this.on('data', function _amtOnData(chunk) this.on('data', function _amtOnData(chunk)
@ -70,7 +91,8 @@ function amt_heci() {
return (ret); 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'); } if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
var args = []; var args = [];
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); } for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
@ -278,8 +300,16 @@ function amt_heci() {
this.getLocalSystemAccount = function getLocalSystemAccount(callback) { this.getLocalSystemAccount = function getLocalSystemAccount(callback) {
var optional = []; var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); } for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) { 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); } {
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); fn.apply(this, opt);
}, callback, optional); }, callback, optional);
} }

View 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;

View file

@ -197,11 +197,18 @@ function UserSessions()
{ {
this.parent.hwnd = h; this.parent.hwnd = h;
// Now that we have a window handle, we can register it to receive Windows Messages // We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
this.parent._wts.WTSRegisterSessionNotification(this.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS); // from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
//this.parent._user32.ACDC_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0); // 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.parent._user32.BATT_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0); this.immediate = setImmediate(function (self)
//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 {
// 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) this._messagepump.on('message', function (msg)
{ {

View file

@ -89,7 +89,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (msg.length < 2) return; if (msg.length < 2) return;
var cmdid = obj.common.ReadShort(msg, 0); var cmdid = obj.common.ReadShort(msg, 0);
if (cmdid == 11) { // MeshCommand_CoreModuleHash 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. // 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. 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. // 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]; var node = nodes[0];
if (node.meshid == obj.dbMeshKey) { if (node.meshid == obj.dbMeshKey) {
// Update the device name & host // Update the device name & host
var newNode = { name: node.name }; var newNode = { "name": node.name };
if (node.intelamt != null) { newNode.intelamt = node.intelamt; } if (node.intelamt != null) { newNode.intelamt = node.intelamt; }
ChangeAgentCoreInfo(newNode); ChangeAgentCoreInfo(newNode);
@ -575,9 +575,6 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
function ChangeAgentCoreInfo(command) { function ChangeAgentCoreInfo(command) {
if ((command == null) || (command == null)) return; // Safety, should never happen. 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 // Check that the mesh exists
var mesh = obj.parent.meshes[obj.dbMeshKey]; var mesh = obj.parent.meshes[obj.dbMeshKey];
if (mesh == null) return; if (mesh == null) return;
@ -589,30 +586,39 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (device.agent) { if (device.agent) {
var changes = [], change = 0; var changes = [], change = 0;
//if (command.users) { console.log(command.users); }
// Check if anything changes // Check if anything changes
if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); } 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.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 (command.intelamt) {
if (!device.intelamt) { device.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.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)) { device.intelamt.state = command.intelamt.state; change = 1; changes.push('AMT state'); } 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)) { device.intelamt.flags = command.intelamt.flags; change = 1; changes.push('AMT flags'); } if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.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 (device.intelamt.flags) { changes.push('AMT flags (' + device.intelamt.flags + ' --> ' + command.intelamt.flags + ')'); } else { changes.push('AMT flags (' + command.intelamt.flags + ')'); }
if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { device.intelamt.uuid = command.intelamt.uuid; change = 1; changes.push('AMT uuid'); } 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 (mesh.mtype == 2) {
if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); } 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. // 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) { if (change == 1) {
// Save to the database
obj.db.Set(device); obj.db.Set(device);
// Event the node change // 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(', ') }; var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id };
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes 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); var device2 = obj.common.Clone(device);
if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
event.node = device; event.node = device;

View file

@ -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' }, 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' }, 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' }, 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' }, 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' }, 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 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' }, 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 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' }, 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' }, 19: { id: 19, localname: 'meshagent_x86_nokvm', rname: 'meshagent', desc: 'Linux x86-32 NoKVM', update: true, amt: true, platform: 'linux' },

View file

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

View file

@ -39,6 +39,14 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
obj.noMouseRotate = false; obj.noMouseRotate = false;
obj.rotation = 0; obj.rotation = 0;
// ###END###{DesktopRotation} // ###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} // ###BEGIN###{DesktopFocus}
obj.mx = 0; // Last mouse x position obj.mx = 0; // Last mouse x position
@ -138,6 +146,9 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
var supportedEncodings = ''; var supportedEncodings = '';
if (obj.useZRLE) supportedEncodings += IntToStr(16); if (obj.useZRLE) supportedEncodings += IntToStr(16);
supportedEncodings += IntToStr(0); 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 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); } if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); }
} }
else if (obj.state == 4) { else if (obj.state == 4) {
var c = obj.acc.charCodeAt(0); switch (obj.acc.charCodeAt(0)) {
if (c == 2) { case 0: // FramebufferUpdate
cmdsize = 1; // This is the bell, do nothing. if (obj.acc.length < 4) return;
} else if (c == 0) { 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.
if (obj.acc.length < 4) return; cmdsize = 4;
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. break;
cmdsize = 4; 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) { 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) { function _putImage(i, x, y) {
// ###BEGIN###{DesktopInband}
if (obj.holding == true) return;
// ###END###{DesktopInband}
// ###BEGIN###{DesktopRotation} // ###BEGIN###{DesktopRotation}
var xx = _arotX(x, y); var xx = _arotX(x, y);
y = _arotY(x, y); y = _arotY(x, y);
@ -416,6 +459,11 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
obj.setRotation = function (x) { obj.setRotation = function (x) {
while (x < 0) { x += 4; } while (x < 0) { x += 4; }
var newrotation = 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; if (newrotation == obj.rotation) return true;
var rw = obj.canvas.canvas.width; var rw = obj.canvas.canvas.width;
var rh = obj.canvas.canvas.height; 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 _fixColor(c) { return (c > 127) ? (c + 32) : c; }
function _SendRefresh() { function _SendRefresh() {
// ###BEGIN###{DesktopInband}
if (obj.holding == true) return;
// ###END###{DesktopInband}
// ###BEGIN###{DesktopFocus} // ###BEGIN###{DesktopFocus}
if (obj.focusmode > 0) { if (obj.focusmode > 0) {
// Request only pixels around the last mouse position // Request only pixels around the last mouse position
@ -477,6 +528,11 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
// ###BEGIN###{Inflate} // ###BEGIN###{Inflate}
obj.inflate.inflateReset(); obj.inflate.inflateReset();
// ###END###{Inflate} // ###END###{Inflate}
// ###BEGIN###{DesktopInband}
obj.onKvmDataPending = [];
obj.onKvmDataAck = -1;
obj.kvmDataSupported = false;
// ###END###{DesktopInband}
for (var i in obj.sparecache) { delete obj.sparecache[i]; } 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)); } 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.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 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

View file

@ -144,8 +144,8 @@
</div> </div>
<div id=p1 style=display:none> <div id=p1 style=display:none>
<div style="float:right" id="devListToolbarViewIcons"> <div style="float:right" id="devListToolbarViewIcons">
<div id=devViewButton1 class="viewSelector" onclick=onDeviceViewChange(1) title="Columns"><div class="viewSelector1"></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="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=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 id=devViewButton4 class=viewSelector onclick=onDeviceViewChange(4) title="Map"><div class="viewSelector4"></div></div>
</div><div><h1>My Devices</h1></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; } } for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
if (index != -1) { if (index != -1) {
var node = nodes[index]; var node = nodes[index];
console.log(node);
// Change the node // Change the node
node.name = message.event.node.name; node.name = message.event.node.name;
node.rname = message.event.node.rname; node.rname = message.event.node.rname;
node.users = message.event.node.users;
node.host = message.event.node.host; node.host = message.event.node.host;
node.desc = message.event.node.desc; node.desc = message.event.node.desc;
node.osdesc = message.event.node.osdesc;
node.publicip = message.event.node.publicip; node.publicip = message.event.node.publicip;
node.iploc = message.event.node.iploc; node.iploc = message.event.node.iploc;
node.wifiloc = message.event.node.wifiloc; node.wifiloc = message.event.node.wifiloc;
@ -1892,6 +1895,7 @@
desk.m.bpp = 1; desk.m.bpp = 1;
desk.m.useZRLE = true; desk.m.useZRLE = true;
desk.m.showmouse = true; desk.m.showmouse = true;
desk.m.onKvmData = function (data) { console.log('KVMData: ' + data); };
//desk.m.onScreenSizeChange = deskAdjust; //desk.m.onScreenSizeChange = deskAdjust;
desk.Start(nodeid, 16994, '*', '*', 0); desk.Start(nodeid, 16994, '*', '*', 0);
desk.contype = 2; desk.contype = 2;
@ -2075,8 +2079,8 @@
function addAgentToMesh(meshid) { function addAgentToMesh(meshid) {
if (xxdialogMode) return; if (xxdialogMode) return;
var mesh = meshes[meshid], x = ''; 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=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=3>Windows (UnInstall)</option><option value=4>Linux (UnInstall)</option></select>') + '<hr>';
// Windows agent install // 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 />"; //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 // 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 += "<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>"; x += "</div>";
// Windows agent uninstall // Windows agent uninstall
@ -3067,6 +3071,12 @@
// Attribute: Intel AMT // Attribute: Intel AMT
//if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel&reg; AMT', node.intelamt.user); } //if (node.intelamt && node.intelamt.user) { x += addDeviceAttribute('Intel&reg; 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). // Attribute: Connectivity (Only show this if more than just the agent is connected).
var connectivity = node.conn; var connectivity = node.conn;
if (connectivity && connectivity > 1) { if (connectivity && connectivity > 1) {
@ -3583,6 +3593,7 @@
desktop.m.useZRLE = (desktopsettings.encoding < 3); desktop.m.useZRLE = (desktopsettings.encoding < 3);
desktop.m.showmouse = desktopsettings.showmouse; desktop.m.showmouse = desktopsettings.showmouse;
desktop.m.onScreenSizeChange = deskAdjust; desktop.m.onScreenSizeChange = deskAdjust;
desktop.m.onKvmData = function (data) { console.log('KVMData: ' + data); };
desktop.Start(desktopNode._id, 16994, '*', '*', 0); desktop.Start(desktopNode._id, 16994, '*', '*', 0);
desktop.contype = 2; desktop.contype = 2;
} else { } else {

View file

@ -1636,11 +1636,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if ((domain == null) || (req.query.id == null)) { res.sendStatus(404); return; } if ((domain == null) || (req.query.id == null)) { res.sendStatus(404); return; }
// If required, check if this user has rights to do this // 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 // Send a specific mesh agent back
var argentInfo = obj.parent.meshAgentBinaries[req.query.id]; 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). // 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 // 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)) { if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid]; var user = obj.users[req.session.userid];
var escUserId = obj.common.escapeFieldName(user._id); 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 ((user == null) || (mesh.links[escUserId] == null) || ((mesh.links[escUserId].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); console.log('5'); 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(); var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();