diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 9983402d..57a0d89d 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index f658c04c..0745e070 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index b37359d4..fcdda123 100644 Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ diff --git a/agents/MeshService.exe b/agents/MeshService.exe index 92b11826..ee628130 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index 4a67e9df..094d7b75 100644 Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index 3db9a837..8b5d94fb 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshagent_arm b/agents/meshagent_arm index 8a4d6c54..e4d50867 100644 Binary files a/agents/meshagent_arm and b/agents/meshagent_arm differ diff --git a/agents/meshagent_pi b/agents/meshagent_pi index a19feb29..a6a5a368 100644 Binary files a/agents/meshagent_pi and b/agents/meshagent_pi differ diff --git a/agents/meshagent_pogo b/agents/meshagent_pogo index 3b14ebcc..dec2a06c 100644 Binary files a/agents/meshagent_pogo and b/agents/meshagent_pogo differ diff --git a/agents/meshagent_poky b/agents/meshagent_poky index 501384e3..40708042 100644 Binary files a/agents/meshagent_poky and b/agents/meshagent_poky differ diff --git a/agents/meshagent_poky64 b/agents/meshagent_poky64 index 0682649f..ba2e5018 100644 Binary files a/agents/meshagent_poky64 and b/agents/meshagent_poky64 differ diff --git a/agents/meshagent_x86 b/agents/meshagent_x86 index b4df66b2..144c5bab 100644 Binary files a/agents/meshagent_x86 and b/agents/meshagent_x86 differ diff --git a/agents/meshagent_x86-64 b/agents/meshagent_x86-64 index 90d69944..5f1e852c 100644 Binary files a/agents/meshagent_x86-64 and b/agents/meshagent_x86-64 differ diff --git a/agents/meshagent_x86-64_nokvm b/agents/meshagent_x86-64_nokvm index 8ffd0d2d..7330ab44 100644 Binary files a/agents/meshagent_x86-64_nokvm and b/agents/meshagent_x86-64_nokvm differ diff --git a/agents/meshagent_x86_nokvm b/agents/meshagent_x86_nokvm index c4b1236f..bc52c3e8 100644 Binary files a/agents/meshagent_x86_nokvm and b/agents/meshagent_x86_nokvm differ diff --git a/agents/meshcmd.js b/agents/meshcmd.js index c5d511ff..8c1225e9 100644 --- a/agents/meshcmd.js +++ b/agents/meshcmd.js @@ -96,7 +96,7 @@ function run(argv) { //console.log('addedModules = ' + JSON.stringify(addedModules)); var actionpath = 'meshaction.txt'; if (args.actionfile != null) { actionpath = args.actionfile; } - var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTPRESENCE']; + var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTINFODEBUG', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTPRESENCE']; // Load the action file var actionfile = null; @@ -372,6 +372,22 @@ function run(argv) { console.log(str + '.'); exit(1); }); + } else if (settings.action == 'amtinfodebug') { + // Display Intel AMT version and activation state + mestate = {}; + var amtMeiModule = require('amt-mei'); + var amtMei = new amtMeiModule(); + amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); + amtMei.getVersion(function (result) { console.log('getVersion: ' + JSON.stringify(result)); }); + amtMei.getProvisioningState(function (result) { console.log('getProvisioningState: ' + JSON.stringify(result)); }); + amtMei.getProvisioningMode(function (result) { console.log('getProvisioningMode: ' + JSON.stringify(result)); }); + amtMei.getEHBCState(function (result) { if (result) { console.log('getEHBCState: ' + JSON.stringify(result)); } }); + amtMei.getControlMode(function (result) { if (result) { console.log('getControlMode: ' + JSON.stringify(result)); } }); + amtMei.getMACAddresses(function (result) { if (result) { console.log('getMACAddresses: ' + JSON.stringify(result)); } }); + amtMei.getLanInterfaceSettings(0, function (result) { console.log('getLanInterfaceSettings0: ' + JSON.stringify(result)); }); + amtMei.getLanInterfaceSettings(1, function (result) { console.log('getLanInterfaceSettings1: ' + JSON.stringify(result)); }); + amtMei.getUuid(function (result) { console.log('getUuid: ' + JSON.stringify(result)); }); + amtMei.getDnsSuffix(function (result) { console.log('getDnsSuffix: ' + JSON.stringify(result)); }); } else if (settings.action == 'amtsavestate') { // Save the entire state of Intel AMT info a JSON file if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } diff --git a/agents/meshcore.js b/agents/meshcore.js index 330ed5e9..91786322 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -14,9 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ + +process.on('uncaughtException', function (ex) { + require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": "uncaughtException1: " + ex }); +}); + + function createMeshCore(agent) { var obj = {}; + /* function borderController() { this.container = null; this.Start = function Start(user) { @@ -45,6 +52,7 @@ function createMeshCore(agent) { } } } + */ require('events').EventEmitter.call(obj, true).createEvent('loggedInUsers_Updated'); obj.on('loggedInUsers_Updated', function () @@ -56,7 +64,7 @@ function createMeshCore(agent) { } sendConsoleText('LogOn Status Changed. Active Users => [' + users.join(', ') + ']'); }); - obj.borderManager = new borderController(); + //obj.borderManager = new borderController(); // MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent. obj.meshCoreInfo = "MeshCore v6"; @@ -82,6 +90,12 @@ function createMeshCore(agent) { var networkMonitor = null; var amtscanner = null; 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 AMTScanner = require("AMTScanner"); @@ -120,7 +134,7 @@ function createMeshCore(agent) { try { var amtMeiLib = require('amt-mei'); amtMei = new amtMeiLib(); - amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); }); + amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; sendPeriodicServerUpdate(); }); amtMeiConnected = 2; //amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); }); } catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; } @@ -909,9 +923,10 @@ function createMeshCore(agent) { var response = null; switch (cmd) { case 'help': { // Displays available commands - response = 'Available commands: help, info, args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, ps, kill, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios, toast, lock, users, border.'; + 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.'; break; } + /* case 'border': { if ((args['_'].length == 1) && (args['_'][0] == 'on')) { @@ -929,6 +944,7 @@ function createMeshCore(agent) { } } break; + */ case 'users': { var retList = []; @@ -1020,15 +1036,24 @@ function createMeshCore(agent) { break; } 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 Info: ' + 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 (obj.osDesc) { response += '\r\nOS: ' + obj.osDesc + '.'; } response += '\r\nModules: ' + addedModules.join(', ') + '.'; - response += '\r\nServerConnected: ' + mesh.isControlChannelConnected + '.'; + response += '\r\nServer Connection: ' + mesh.isControlChannelConnected + ', State: ' + meshServerConnectionState + '.'; + response += '\r\nLastInfo: ' + lastSelfInfo + '.'; var oldNodeId = db.Get('OldNodeId'); if (oldNodeId != null) { response += '\r\nOldNodeID: ' + oldNodeId + '.'; } - response += '\r\nServerState: ' + meshServerConnectionState + '.'; - 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 + '.'; } + break; + } + case 'osinfo': { // Return the operating system information + var i = 1; + if (args['_'].length > 0) { i = parseInt(args['_'][0]); response = 'Calling ' + i + ' times.'; } + for (var j = 0; j < i; j++) { + var pr = require('os').name(); + pr.sessionid = sessionid; + pr.then(function (v) { sendConsoleText("OS: " + v, this.sessionid); }); } break; } @@ -1036,6 +1061,26 @@ function createMeshCore(agent) { 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]) }; + mesh.SendCommand(flags); + response = JSON.stringify(flags); + } + break; + } case 'args': { // Displays parsed command arguments response = 'args ' + objToString(args, 0, ' ', true); break; @@ -1345,15 +1390,17 @@ function createMeshCore(agent) { function buildSelfInfo(func) { getAmtInfo(function (meinfo) { var r = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": obj.meshCoreCapabilities }; - 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 } - } + 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); }); } @@ -1374,10 +1421,11 @@ 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 ((force == true) || (selfInfoStr != lastSelfInfo)) { mesh.SendCommand(selfInfo); lastSelfInfo = selfInfoStr; } + if (selfInfoStr != lastSelfInfo) { mesh.SendCommand(selfInfo); lastSelfInfo = selfInfoStr; } }); } @@ -1445,10 +1493,9 @@ function createMeshCore(agent) { } catch (e) { amtLmsState = -1; amtLms = null; } // Check if the control channel is connected - if (mesh.isControlChannelConnected) { - sendPeriodicServerUpdate(true); // Send the server update - } + if (mesh.isControlChannelConnected) { handleServerConnection(1); } + /* require('user-sessions').on('changed', function onUserSessionChanged() { require('user-sessions').enumerateUsers().then(function (users) @@ -1461,6 +1508,7 @@ function createMeshCore(agent) { 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'); }); + */ //console.log('Stopping.'); //process.exit(); } @@ -1733,14 +1781,18 @@ function createMeshCore(agent) { // Module startup // -var xexports = null, mainMeshCore = null; -try { xexports = module.exports; } catch (e) { } +try { + var xexports = null, mainMeshCore = null; + try { xexports = module.exports; } catch (e) { } -if (xexports != null) { - // If we are running within NodeJS, export the core - module.exports.createMeshCore = createMeshCore; -} else { - // If we are not running in NodeJS, launch the core - mainMeshCore = createMeshCore(); - mainMeshCore.start(null); -} + if (xexports != null) { + // If we are running within NodeJS, export the core + module.exports.createMeshCore = createMeshCore; + } else { + // If we are not running in NodeJS, launch the core + mainMeshCore = createMeshCore(); + mainMeshCore.start(null); + } +} catch (ex) { + require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": "uncaughtException2: " + ex }); +} \ No newline at end of file diff --git a/agents/modules_meshcmd/amt-lme.js b/agents/modules_meshcmd/amt-lme.js index 2e8a74de..725cfcda 100644 --- a/agents/modules_meshcmd/amt-lme.js +++ b/agents/modules_meshcmd/amt-lme.js @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ - var MemoryStream = require('MemoryStream'); var lme_id = 0; // Our next channel identifier var lme_port_offset = 0; // Debug: Set this to "-100" to bind to 16892 & 16893 and IN_ADDRANY. This is for LMS debugging. @@ -38,6 +37,7 @@ var APF_CHANNEL_DATA = 94; var APF_CHANNEL_CLOSE = 97; var APF_PROTOCOLVERSION = 192; + function lme_object() { this.ourId = ++lme_id; this.amtId = -1; @@ -266,7 +266,7 @@ function lme_heci(options) { this.sockets[rChannelId].bufferedStream.emit('readable'); } } else { - //console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST'); + console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST'); } break; case APF_CHANNEL_DATA: @@ -379,14 +379,16 @@ function lme_heci(options) { buffer.writeUInt32BE(0xFFFFFFFF, 13); // Reserved this.write(buffer); - //var buffer = Buffer.alloc(17); - //buffer.writeUInt8(APF_CHANNEL_OPEN_FAILURE, 0); - //buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel - //buffer.writeUInt32BE(2, 5); // Reason code - //buffer.writeUInt32BE(0, 9); // Reserved - //buffer.writeUInt32BE(0, 13); // Reserved - //this.write(buffer); - //console.log('Sent APF_CHANNEL_OPEN_FAILURE', channelSender); + /* + var buffer = Buffer.alloc(17); + buffer.writeUInt8(APF_CHANNEL_OPEN_FAILURE, 0); + buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel + buffer.writeUInt32BE(2, 5); // Reason code + buffer.writeUInt32BE(0, 9); // Reserved + buffer.writeUInt32BE(0, 13); // Reserved + this.write(buffer); + console.log('Sent APF_CHANNEL_OPEN_FAILURE', channelSender); + */ break; } diff --git a/agents/modules_meshcmd/amt-wsman-duk.js b/agents/modules_meshcmd/amt-wsman-duk.js index 7df52f1c..ccc2a4e0 100644 --- a/agents/modules_meshcmd/amt-wsman-duk.js +++ b/agents/modules_meshcmd/amt-wsman-duk.js @@ -30,7 +30,6 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) obj.FailAllError = 0; // Set this to non-zero to fail all AJAX calls with that error status, 999 causes responses to be silent. obj.digest = null; obj.RequestCount = 0; - obj.requests = {}; if (arguments.length == 1 && typeof(arguments[0] == 'object')) { @@ -90,12 +89,9 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) } var request = { protocol: (obj.tls == 1 ? 'https:' : 'http:'), method: 'POST', host: obj.host, path: '/wsman', port: obj.port, rejectUnauthorized: false, checkServerIdentity: function (cert) { console.log('checkServerIdentity', JSON.stringify(cert)); } }; var req = obj.digest.request(request); - req.reqid = obj.RequestCount++; - obj.requests[req.reqid] = req; // Keep a reference to the request object so it does not get disposed. //console.log('Request ' + (obj.RequestCount++)); - req.on('error', function (e) { delete obj.requests[this.reqid]; obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); }); + req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); }); req.on('response', function (response) { - response.reqid = this.reqid; //console.log('Response: ' + response.statusCode); if (response.statusCode != 200) { //console.log('ERR:' + JSON.stringify(response)); @@ -103,7 +99,7 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) } else { response.acc = ''; response.on('data', function (data2) { this.acc += data2; }); - response.on('end', function () { delete obj.requests[this.reqid]; obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); }); + response.on('end', function () { obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); }); } }); diff --git a/agents/modules_meshcmd/amt-xml.js b/agents/modules_meshcmd/amt-xml.js index 605d8baf..61fd4a33 100644 --- a/agents/modules_meshcmd/amt-xml.js +++ b/agents/modules_meshcmd/amt-xml.js @@ -14,6 +14,9 @@ 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) { } + + // Parse XML and return JSON module.exports.ParseWsman = function (xml) { try { @@ -36,7 +39,7 @@ module.exports.ParseWsman = function (xml) { } return r; } catch (e) { - console.log("Unable to parse XML: " + xml); + console.error("Unable to parse XML: " + xml, e); return null; } } @@ -103,7 +106,6 @@ function _PutObjToBodyXml(resuri, putObj) { } // This is a drop-in replacement to _turnToXml() that works without xml parser dependency. -try { Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : null); } }); } catch (ex) { } function _treeBuilder() { this.tree = []; this.push = function (element) { this.tree.push(element); }; diff --git a/agents/modules_meshcmd/amt.js b/agents/modules_meshcmd/amt.js index e0dbe0aa..3b447e30 100644 --- a/agents/modules_meshcmd/amt.js +++ b/agents/modules_meshcmd/amt.js @@ -202,9 +202,6 @@ function AmtStackCreateService(wsmanStack) { obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func, tag, pri, selectors); } obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func, tag, pri, selectors); } obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func, tag, pri, selectors); } - //obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func); } - //obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func); } - //obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func); } obj.AMT_AgentPresenceWatchdog_AddAction = function (OldState, NewState, EventOnTransition, ActionSd, ActionEac, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AddAction", { "OldState": OldState, "NewState": NewState, "EventOnTransition": EventOnTransition, "ActionSd": ActionSd, "ActionEac": ActionEac }, callback_func, tag, pri, selectors); } obj.AMT_AgentPresenceWatchdog_DeleteAllActions = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "DeleteAllActions", {}, callback_func, tag, pri, selectors); } obj.AMT_AgentPresenceWatchdogAction_GetActionEac = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdogAction", "GetActionEac", {}, callback_func); } @@ -264,7 +261,7 @@ function AmtStackCreateService(wsmanStack) { obj.AMT_MessageLog_FreezeLog = function (Freeze, callback_func) { obj.Exec("AMT_MessageLog", "FreezeLog", { "Freeze": Freeze }, callback_func); } obj.AMT_PublicKeyManagementService_AddCRL = function (Url, SerialNumbers, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddCRL", { "Url": Url, "SerialNumbers": SerialNumbers }, callback_func); } obj.AMT_PublicKeyManagementService_ResetCRLList = function (_method_dummy, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "ResetCRLList", { "_method_dummy": _method_dummy }, callback_func); } - obj.AMT_PublicKeyManagementService_AddCertificate = function (CertificateBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddCertificate", { "CertificateBlob": CertificateBlob }, callback_func); } + obj.AMT_PublicKeyManagementService_AddCertificate = function (CertificateBlob, callback_func, tag) { obj.Exec("AMT_PublicKeyManagementService", "AddCertificate", { "CertificateBlob": CertificateBlob }, callback_func, tag); } obj.AMT_PublicKeyManagementService_AddTrustedRootCertificate = function (CertificateBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddTrustedRootCertificate", { "CertificateBlob": CertificateBlob }, callback_func); } obj.AMT_PublicKeyManagementService_AddKey = function (KeyBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddKey", { "KeyBlob": KeyBlob }, callback_func); } obj.AMT_PublicKeyManagementService_GeneratePKCS10Request = function (KeyPair, DNName, Usage, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "GeneratePKCS10Request", { "KeyPair": KeyPair, "DNName": DNName, "Usage": Usage }, callback_func); } @@ -275,7 +272,7 @@ function AmtStackCreateService(wsmanStack) { obj.AMT_RemoteAccessService_AddMpServer = function (AccessInfo, InfoFormat, Port, AuthMethod, Certificate, Username, Password, CN, callback_func) { obj.Exec("AMT_RemoteAccessService", "AddMpServer", { "AccessInfo": AccessInfo, "InfoFormat": InfoFormat, "Port": Port, "AuthMethod": AuthMethod, "Certificate": Certificate, "Username": Username, "Password": Password, "CN": CN }, callback_func); } obj.AMT_RemoteAccessService_AddRemoteAccessPolicyRule = function (Trigger, TunnelLifeTime, ExtendedData, MpServer, callback_func) { obj.Exec("AMT_RemoteAccessService", "AddRemoteAccessPolicyRule", { "Trigger": Trigger, "TunnelLifeTime": TunnelLifeTime, "ExtendedData": ExtendedData, "MpServer": MpServer }, callback_func); } obj.AMT_RemoteAccessService_CloseRemoteAccessConnection = function (_method_dummy, callback_func) { obj.Exec("AMT_RemoteAccessService", "CloseRemoteAccessConnection", { "_method_dummy": _method_dummy }, callback_func); } - obj.AMT_SetupAndConfigurationService_CommitChanges = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "CommitChanges", { "_method_dummy": _method_dummy }, callback_func); } + obj.AMT_SetupAndConfigurationService_CommitChanges = function (_method_dummy, callback_func, tag) { obj.Exec("AMT_SetupAndConfigurationService", "CommitChanges", { "_method_dummy": _method_dummy }, callback_func, tag); } obj.AMT_SetupAndConfigurationService_Unprovision = function (ProvisioningMode, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "Unprovision", { "ProvisioningMode": ProvisioningMode }, callback_func); } obj.AMT_SetupAndConfigurationService_PartialUnprovision = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "PartialUnprovision", { "_method_dummy": _method_dummy }, callback_func); } obj.AMT_SetupAndConfigurationService_ResetFlashWearOutProtection = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "ResetFlashWearOutProtection", { "_method_dummy": _method_dummy }, callback_func); } @@ -292,6 +289,7 @@ function AmtStackCreateService(wsmanStack) { obj.AMT_SystemPowerScheme_SetPowerScheme = function (callback_func, schemeInstanceId, tag) { obj.Exec("AMT_SystemPowerScheme", "SetPowerScheme", {}, callback_func, tag, 0, { "InstanceID": schemeInstanceId }); } obj.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch = function (callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "GetLowAccuracyTimeSynch", {}, callback_func, tag); } obj.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch = function (Ta0, Tm1, Tm2, callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "SetHighAccuracyTimeSynch", { "Ta0": Ta0, "Tm1": Tm1, "Tm2": Tm2 }, callback_func, tag); } + obj.AMT_TLSCredentialContext_Create = function AMT_TLSCredentialContext_Create(ElementInContext, ElementProvidingContext, callback_func, tag) { obj.Create("AMT_TLSCredentialContext", { "ElementInContext": ElementInContext, "ElementProvidingContext": ElementProvidingContext }, callback_func, tag); } obj.AMT_UserInitiatedConnectionService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_UserInitiatedConnectionService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); } obj.AMT_WebUIService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func, tag) { obj.Exec("AMT_WebUIService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func, tag); } obj.AMT_WiFiPortConfigurationService_AddWiFiSettings = function (WiFiEndpoint, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { obj.ExecWithXml("AMT_WiFiPortConfigurationService", "AddWiFiSettings", { "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); } @@ -765,18 +763,18 @@ function AmtStackCreateService(wsmanStack) { x['Initiator'] = 'KVM Default Port'; ptr = 5; } - + // Read timestamp TimeStamp = ReadInt(e, ptr); x['Time'] = new Date((TimeStamp + (t.getTimezoneOffset() * 60)) * 1000); ptr += 4; - + // Read network access x['MCLocationType'] = e[ptr++]; var netlen = e[ptr++]; x['NetAddress'] = e.slice(ptr, ptr + netlen).toString(); - + // Read extended data ptr += netlen; var exlen = e[ptr++]; @@ -990,7 +988,7 @@ function AmtStackCreateService(wsmanStack) { // Convert a byte array of SID into string function GetSidString(sid) { var r = "S-" + sid.charCodeAt(0) + "-" + sid.charCodeAt(7); - for (var i = 2; i < (sid.length / 4) ; i++) r += "-" + ReadIntX(sid, i * 4); + for (var i = 2; i < (sid.length / 4); i++) r += "-" + ReadIntX(sid, i * 4); return r; } diff --git a/agents/modules_meshcmd/process-manager.js b/agents/modules_meshcmd/process-manager.js index c09f7ac4..25b78306 100644 --- a/agents/modules_meshcmd/process-manager.js +++ b/agents/modules_meshcmd/process-manager.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ + var GM = require('_GenericMarshal'); // Used on Windows and Linux to get information about running processes @@ -21,7 +22,8 @@ function processManager() { this._ObjectID = 'process-manager'; // Used for debugging, allows you to get the object type at runtime. // Setup the platform specific calls. - switch (process.platform) { + switch (process.platform) + { case 'win32': this._kernel32 = GM.CreateNativeProxy('kernel32.dll'); this._kernel32.CreateMethod('GetLastError'); @@ -30,17 +32,26 @@ function processManager() { this._kernel32.CreateMethod('Process32Next'); break; case 'linux': + case 'darwin': this._childProcess = require('child_process'); break; default: throw (process.platform + ' not supported'); break; } - + this.enumerateProcesses = function enumerateProcesses() + { + var promise = require('promise'); + var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; }); + this.getProcesses(function (ps, prom) { prom._res(ps); }, ret); + return (ret); + } // Return a object of: pid -> process information. - this.getProcesses = function getProcesses(callback) { - switch (process.platform) { - default: // This is not a supported platform. + this.getProcesses = function getProcesses(callback) + { + switch(process.platform) + { + default: throw ('Enumerating processes on ' + process.platform + ' not supported'); break; case 'win32': // Windows processes @@ -49,8 +60,9 @@ function processManager() { var info = GM.CreateVariable(304); info.toBuffer().writeUInt32LE(304, 0); var nextProcess = this._kernel32.Process32First(h, info); - while (nextProcess.Val) { - retVal[info.Deref(8, 4).toBuffer().readUInt32LE(0)] = { cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String }; + while (nextProcess.Val) + { + retVal[info.Deref(8, 4).toBuffer().readUInt32LE(0)] = { pid: info.Deref(8, 4).toBuffer().readUInt32LE(0), cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String }; nextProcess = this._kernel32.Process32Next(h, info); } if (callback) { callback.apply(this, [retVal]); } @@ -64,40 +76,80 @@ function processManager() { p.callback = callback; p.args = []; for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); } - p.on('exit', function onGetProcesses() { - delete this.Parent._psp[this.pid]; + p.on('exit', function onGetProcesses() + { + delete this.Parent._psp[this.pid]; var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0; - for (var i in lines) { + for (var i in lines) + { var tokens = lines[i].split(' '); var tokenList = []; - for (var x in tokens) { + for(var x in tokens) + { if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; } - if (i > 0 && tokens[x]) { tokenList.push(tokens[x]); } + if (i > 0 && tokens[x]) { tokenList.push(tokens[x]);} } if (i > 0) { - if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; } + if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { pid: key.PID, user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; } } } - if (this.callback) { + if (this.callback) + { this.args.unshift(retVal); this.callback.apply(this.parent, this.args); } }); p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); }); break; + case 'darwin': + var promise = require('promise'); + var p = new promise(function (res, rej) { this._res = res; this._rej = rej; }); + p.pm = this; + p.callback = callback; + p.args = []; + for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); } + p.child = this._childProcess.execFile("/bin/ps", ["ps", "-xa"]); + p.child.promise = p; + p.child.stdout.ps = ''; + p.child.stdout.on('data', function (chunk) { this.ps += chunk.toString(); }); + p.child.on('exit', function () + { + var lines = this.stdout.ps.split('\n'); + var pidX = lines[0].split('PID')[0].length + 3; + var cmdX = lines[0].split('CMD')[0].length; + var ret = {}; + for (var i = 1; i < lines.length; ++i) + { + if (lines[i].length > 0) + { + ret[lines[i].substring(0, pidX).trim()] = { pid: lines[i].substring(0, pidX).trim(), cmd: lines[i].substring(cmdX) }; + } + } + this.promise._res(ret); + }); + p.then(function (ps) + { + this.args.unshift(ps); + this.callback.apply(this.pm, this.args); + }); + break; } }; - + // Get information about a specific process on Linux - this.getProcessInfo = function getProcessInfo(pid) { - switch (process.platform) { + this.getProcessInfo = function getProcessInfo(pid) + { + switch(process.platform) + { default: throw ('getProcessInfo() not supported for ' + process.platform); break; case 'linux': var status = require('fs').readFileSync('/proc/' + pid + '/status'); - var info = {}, lines = status.toString().split('\n'); - for (var i in lines) { + var info = {}; + var lines = status.toString().split('\n'); + for(var i in lines) + { var tokens = lines[i].split(':'); if (tokens.length > 1) { tokens[1] = tokens[1].trim(); } info[tokens[0]] = tokens[1]; diff --git a/agents/modules_meshcmd/promise.js b/agents/modules_meshcmd/promise.js index e764a630..227b23ac 100644 --- a/agents/modules_meshcmd/promise.js +++ b/agents/modules_meshcmd/promise.js @@ -16,10 +16,32 @@ limitations under the License. var refTable = {}; +function event_switcher_helper(desired_callee, target) +{ + this._ObjectID = 'event_switcher'; + this.func = function func() + { + var args = []; + for(var i in arguments) + { + args.push(arguments[i]); + } + return (func.target.apply(func.desired, args)); + }; + this.func.desired = desired_callee; + this.func.target = target; + this.func.self = this; +} +function event_switcher(desired_callee, target) +{ + return (new event_switcher_helper(desired_callee, target)); +} + function Promise(promiseFunc) { this._ObjectID = 'promise'; - this._internal = { promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [] }; + this.promise = this; + this._internal = { _ObjectID: 'promise.internal', promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [] }; require('events').EventEmitter.call(this._internal); this._internal.on('_eventHook', function (eventName, eventCallback) { @@ -82,21 +104,21 @@ function Promise(promiseFunc) }; this.catch = function(func) { - this._internal.once('settled', func); + this._internal.once('rejected', event_switcher(this, func).func); } this.finally = function (func) { - this._internal.once('settled', func); + this._internal.once('settled', event_switcher(this, func).func); }; this.then = function (resolved, rejected) { - if (resolved) { this._internal.once('resolved', resolved); } - if (rejected) { this._internal.once('rejected', rejected); } + if (resolved) { this._internal.once('resolved', event_switcher(this, resolved).func); } + if (rejected) { this._internal.once('rejected', event_switcher(this, rejected).func); } var retVal = new Promise(function (r, j) { }); - this._internal.once('resolved', retVal._internal.resolver); this._internal.once('rejected', retVal._internal.rejector); + retVal.parentPromise = this; return (retVal); }; diff --git a/agents/modules_meshcmd/smbios.js b/agents/modules_meshcmd/smbios.js index e23c6ffb..61153a58 100644 --- a/agents/modules_meshcmd/smbios.js +++ b/agents/modules_meshcmd/smbios.js @@ -21,7 +21,18 @@ var RSMB = 1381190978; var memoryLocation = { 0x1: 'Other', 0x2: 'Unknown', 0x3: 'System Board', 0x4: 'ISA', 0x5: 'EISA', 0x6: 'PCI', 0x7: 'MCA', 0x8: 'PCMCIA', 0x9: 'Proprietary', 0xA: 'NuBus', 0xA0: 'PC-98/C20', 0xA1: 'PC-98/C24', 0xA2: 'PC-98/E', 0xA3: 'PC-98/LB' }; var wakeReason = ['Reserved', 'Other', 'Unknown', 'APM Timer', 'Modem Ring', 'LAN', 'Power Switch', 'PCI', 'AC Power']; -function SMBiosTables() { +// Fill the left with zeros until the string is of a given length +function zeroLeftPad(str, len) +{ + if ((len == null) && (typeof (len) != 'number')) { return null; } + if (str == null) str = ''; // If null, this is to generate zero leftpad string + var zlp = ''; + for (var i = 0; i < len - str.length; i++) { zlp += '0'; } + return zlp + str; +} + +function SMBiosTables() +{ this._ObjectID = 'SMBiosTable'; if (process.platform == 'win32') { this._marshal = require('_GenericMarshal'); @@ -181,12 +192,21 @@ function SMBiosTables() { } return (retVal); }; - this.systemInfo = function systemInfo(data) { + this.systemInfo = function systemInfo(data) + { if (!data) { throw ('no data'); } var retVal = { _ObjectID: 'SMBiosTables.systemInfo' }; - if (data[1]) { + if (data[1]) + { var si = data[1].peek(); - retVal.uuid = si.slice(4, 20).toString('hex'); + var uuid = si.slice(4, 20); + + retVal.uuid = [zeroLeftPad(uuid.readUInt32LE(0).toString(16), 8), + zeroLeftPad(uuid.readUInt16LE(4).toString(16), 4), + zeroLeftPad(uuid.readUInt16LE(6).toString(16), 4), + zeroLeftPad(uuid.readUInt16BE(8).toString(16), 4), + zeroLeftPad(uuid.slice(10).toString('hex').toLowerCase(), 12)].join('-'); + retVal.wakeReason = wakeReason[si[20]]; } return (retVal); diff --git a/agents/modules_meshcmd/user-sessions.js b/agents/modules_meshcmd/user-sessions.js index 3d8571ad..6ca26278 100644 --- a/agents/modules_meshcmd/user-sessions.js +++ b/agents/modules_meshcmd/user-sessions.js @@ -17,6 +17,13 @@ limitations under the License. var NOTIFY_FOR_THIS_SESSION = 0; var NOTIFY_FOR_ALL_SESSIONS = 1; var WM_WTSSESSION_CHANGE = 0x02B1; +var WM_POWERBROADCAST = 0x218; +var PBT_POWERSETTINGCHANGE = 0x8013; +var PBT_APMSUSPEND = 0x4; +var PBT_APMRESUMESUSPEND = 0x7; +var PBT_APMRESUMEAUTOMATIC = 0x12; +var PBT_APMPOWERSTATUSCHANGE = 0xA; + var WTS_CONSOLE_CONNECT = (0x1); var WTS_CONSOLE_DISCONNECT = (0x2); var WTS_REMOTE_CONNECT = (0x3); @@ -29,6 +36,10 @@ var WTS_SESSION_REMOTE_CONTROL = (0x9); var WTS_SESSION_CREATE = (0xA); var WTS_SESSION_TERMINATE = (0xB); +var GUID_ACDC_POWER_SOURCE; +var GUID_BATTERY_PERCENTAGE_REMAINING; +var GUID_CONSOLE_DISPLAY_STATE; + function UserSessions() { this._ObjectID = 'user-sessions'; @@ -49,7 +60,15 @@ function UserSessions() { p.__resolver(users); }; - this.Current(p.__handler); + try + { + this.Current(p.__handler); + } + catch(e) + { + p.__rejector(e); + } + p.parent = this; return (p); } @@ -65,6 +84,29 @@ function UserSessions() this._wts.CreateMethod('WTSRegisterSessionNotification'); this._wts.CreateMethod('WTSUnRegisterSessionNotification'); this._wts.CreateMethod('WTSFreeMemory'); + this._user32 = this._marshal.CreateNativeProxy('user32.dll'); + this._user32.CreateMethod('RegisterPowerSettingNotification'); + this._user32.CreateMethod('UnregisterPowerSettingNotification'); + this._rpcrt = this._marshal.CreateNativeProxy('Rpcrt4.dll'); + this._rpcrt.CreateMethod('UuidFromStringA'); + this._rpcrt.StringToUUID = function StringToUUID(guid) + { + var retVal = StringToUUID.us._marshal.CreateVariable(16); + if(StringToUUID.us._rpcrt.UuidFromStringA(StringToUUID.us._marshal.CreateVariable(guid), retVal).Val == 0) + { + return (retVal); + } + else + { + throw ('Could not convert string to UUID'); + } + } + this._rpcrt.StringToUUID.us = this; + + GUID_ACDC_POWER_SOURCE = this._rpcrt.StringToUUID('5d3e9a59-e9D5-4b00-a6bd-ff34ff516548'); + GUID_BATTERY_PERCENTAGE_REMAINING = this._rpcrt.StringToUUID('a7ad8041-b45a-4cae-87a3-eecbb468a9e1'); + GUID_CONSOLE_DISPLAY_STATE = this._rpcrt.StringToUUID('6fe69556-704a-47a0-8f24-c28d936fda47'); + this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init']; this.InfoClass = { @@ -146,45 +188,112 @@ function UserSessions() return (retVal); }; - this._immediate = setImmediate(function (self) - { - if (self._serviceHooked) { return; } // If we were hooked by a service, we won't need to do anything further - // We need to spin up a message pump, and fetch a window handle - var message_pump = require('win-message-pump'); - self._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE }); - self._messagepump.on('exit', function (code) { self._wts.WTSUnRegisterSessionNotification(self.hwnd); }); - self._messagepump.on('hwnd', function (h) + // We need to spin up a message pump, and fetch a window handle + var message_pump = require('win-message-pump'); + this._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE }); this._messagepump.parent = this; + this._messagepump.on('exit', function (code) { this.parent._wts.WTSUnRegisterSessionNotification(this.parent.hwnd); }); + this._messagepump.on('hwnd', function (h) + { + 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 + }); + this._messagepump.on('message', function (msg) + { + switch(msg.message) { - self.hwnd = h; - // Now that we have a window handle, we can register it to receive Windows Messages - self._wts.WTSRegisterSessionNotification(self.hwnd, NOTIFY_FOR_ALL_SESSIONS); - }); - self._messagepump.on('message', function (msg) - { - if (msg.message == WM_WTSSESSION_CHANGE) - { + case WM_WTSSESSION_CHANGE: switch(msg.wparam) { case WTS_SESSION_LOCK: - self.enumerateUsers().then(function (users) + this.parent.enumerateUsers().then(function (users) { - if (users[msg.lparam]) { self.emit('locked', users[msg.lparam]); } + if (users[msg.lparam]) { this.parent.emit('locked', users[msg.lparam]); } }); break; case WTS_SESSION_UNLOCK: - self.enumerateUsers().then(function (users) + this.parent.enumerateUsers().then(function (users) { - if (users[msg.lparam]) { self.emit('unlocked', users[msg.lparam]); } + if (users[msg.lparam]) { this.parent.emit('unlocked', users[msg.lparam]); } }); break; + case WTS_SESSION_LOGON: + case WTS_SESSION_LOGOFF: + this.parent.emit('changed'); + break; } - } - }); - }, this); + break; + case WM_POWERBROADCAST: + switch(msg.wparam) + { + default: + console.log('WM_POWERBROADCAST [UNKNOWN wparam]: ' + msg.wparam); + break; + case PBT_APMSUSPEND: + require('power-monitor').emit('sx', 'SLEEP'); + break; + case PBT_APMRESUMEAUTOMATIC: + require('power-monitor').emit('sx', 'RESUME_NON_INTERACTIVE'); + break; + case PBT_APMRESUMESUSPEND: + require('power-monitor').emit('sx', 'RESUME_INTERACTIVE'); + break; + case PBT_APMPOWERSTATUSCHANGE: + require('power-monitor').emit('changed'); + break; + case PBT_POWERSETTINGCHANGE: + var lparam = this.parent._marshal.CreatePointer(Buffer.from(msg.lparam_hex, 'hex')); + var data = lparam.Deref(20, lparam.Deref(16, 4).toBuffer().readUInt32LE(0)).toBuffer(); + switch(lparam.Deref(0, 16).toBuffer().toString('hex')) + { + case GUID_ACDC_POWER_SOURCE.Deref(0, 16).toBuffer().toString('hex'): + switch(data.readUInt32LE(0)) + { + case 0: + require('power-monitor').emit('acdc', 'AC'); + break; + case 1: + require('power-monitor').emit('acdc', 'BATTERY'); + break; + case 2: + require('power-monitor').emit('acdc', 'HOT'); + break; + } + break; + case GUID_BATTERY_PERCENTAGE_REMAINING.Deref(0, 16).toBuffer().toString('hex'): + require('power-monitor').emit('batteryLevel', data.readUInt32LE(0)); + break; + case GUID_CONSOLE_DISPLAY_STATE.Deref(0, 16).toBuffer().toString('hex'): + switch(data.readUInt32LE(0)) + { + case 0: + require('power-monitor').emit('display', 'OFF'); + break; + case 1: + require('power-monitor').emit('display', 'ON'); + break; + case 2: + require('power-monitor').emit('display', 'DIMMED'); + break; + } + break; + } + break; + } + break; + default: + break; + } + }); } - else + else if(process.platform == 'linux') { + var dbus = require('linux-dbus'); this._linuxWatcher = require('fs').watch('/var/run/utmp'); this._linuxWatcher.user_session = this; this._linuxWatcher.on('change', function (a, b) @@ -336,6 +445,112 @@ function UserSessions() return (retVal); } + this._recheckLoggedInUsers = function _recheckLoggedInUsers() + { + this.enumerateUsers().then(function (u) + { + + if (u.Active.length > 0) + { + // There is already a user logged in, so we can monitor DBUS for lock/unlock + if (this.parent._linux_lock_watcher != null && this.parent._linux_lock_watcher.uid != u.Active[0].uid) + { + delete this.parent._linux_lock_watcher; + } + this.parent._linux_lock_watcher = new dbus(process.env['XDG_CURRENT_DESKTOP'] == 'Unity' ? 'com.ubuntu.Upstart0_6' : 'org.gnome.ScreenSaver', u.Active[0].uid); + this.parent._linux_lock_watcher.user_session = this.parent; + this.parent._linux_lock_watcher.on('signal', function (s) + { + var p = this.user_session.enumerateUsers(); + p.signalData = s.data[0]; + p.then(function (u) + { + switch (this.signalData) + { + case true: + case 'desktop-lock': + this.parent.emit('locked', u.Active[0]); + break; + case false: + case 'desktop-unlock': + this.parent.emit('unlocked', u.Active[0]); + break; + } + }); + }); + } + else if (this.parent._linux_lock_watcher != null) + { + delete this.parent._linux_lock_watcher; + } + }); + + }; + this.on('changed', this._recheckLoggedInUsers); // For linux Lock/Unlock monitoring, we need to watch for LogOn/LogOff, and keep track of the UID. + + + // First step, is to see if there is a user logged in: + this._recheckLoggedInUsers(); + } + else if(process.platform == 'darwin') + { + this._idTable = function() + { + var table = {}; + var child = require('child_process').execFile('/usr/bin/id', ['id']); + child.stdout.str = ''; + child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); + child.waitExit(); + + var lines = child.stdout.str.split('\n')[0].split(' '); + for (var i = 0; i < lines.length; ++i) { + var types = lines[i].split('='); + var tokens = types[1].split(','); + table[types[0]] = {}; + + for (var j in tokens) { + var idarr = tokens[j].split('('); + var id = idarr[0]; + var name = idarr[1].substring(0, idarr[1].length - 1).trim(); + table[types[0]][name] = id; + table[types[0]][id] = name; + } + } + return (table); + } + this.Current = function (cb) + { + var users = {}; + var table = this._idTable(); + var child = require('child_process').execFile('/usr/bin/last', ['last']); + child.stdout.str = ''; + child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); + child.waitExit(); + + var lines = child.stdout.str.split('\n'); + for (var i = 0; i < lines.length && lines[i].length > 0; ++i) + { + if (!users[lines[i].split(' ')[0]]) + { + try + { + users[lines[i].split(' ')[0]] = { Username: lines[i].split(' ')[0], State: lines[i].split('still logged in').length > 1 ? 'Active' : 'Inactive', uid: table.uid[lines[i].split(' ')[0]] }; + } + catch(e) + {} + } + else + { + if(users[lines[i].split(' ')[0]].State != 'Active' && lines[i].split('still logged in').length > 1) + { + users[lines[i].split(' ')[0]].State = 'Active'; + } + } + } + + Object.defineProperty(users, 'Active', { value: showActiveOnly(users) }); + if (cb) { cb.call(this, users); } + } } } function showActiveOnly(source) diff --git a/agents/modules_meshcore/power-monitor.js b/agents/modules_meshcore/power-monitor.js new file mode 100644 index 00000000..96eaabef --- /dev/null +++ b/agents/modules_meshcore/power-monitor.js @@ -0,0 +1,34 @@ +/* +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. +*/ + +function powerMonitor() +{ + this._ObjectID = 'power-monitor'; + require('events').EventEmitter.call(this, true) + .createEvent('changed') + .createEvent('sx') + .createEvent('batteryLevel') + .createEvent('acdc') + .createEvent('display'); + + this._i = setImmediate(function (self) + { + require('user-sessions'); // This is needed because this is where the Windows Messages are processed for these events + delete self._i; + }, this); +} + +module.exports = new powerMonitor(); \ No newline at end of file diff --git a/agents/modules_meshcore/user-sessions.js b/agents/modules_meshcore/user-sessions.js index 694f4501..6ca26278 100644 --- a/agents/modules_meshcore/user-sessions.js +++ b/agents/modules_meshcore/user-sessions.js @@ -199,9 +199,9 @@ function UserSessions() // 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); + //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 }); this._messagepump.on('message', function (msg) { diff --git a/meshcentral.js b/meshcentral.js index 5000a312..e5c72010 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1087,14 +1087,16 @@ function CreateMeshCentralServer(config, args) { // Update server state. Writes a server state file. var meshServerState = {}; obj.updateServerState = function (name, val) { - if ((name != null) && (val != null)) { - var changed = false; - if ((name != null) && (meshServerState[name] != val)) { if ((val == null) && (meshServerState[name] != null)) { delete meshServerState[name]; changed = true; } else { if (meshServerState[name] != val) { meshServerState[name] = val; changed = true; } } } - if (changed == false) return; - } - var r = 'time=' + Date.now() + '\r\n'; - for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); } - obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r); + try { + if ((name != null) && (val != null)) { + var changed = false; + if ((name != null) && (meshServerState[name] != val)) { if ((val == null) && (meshServerState[name] != null)) { delete meshServerState[name]; changed = true; } else { if (meshServerState[name] != val) { meshServerState[name] = val; changed = true; } } } + if (changed == false) return; + } + var r = 'time=' + Date.now() + '\r\n'; + for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); } + obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r); // Try to write the server state, this may fail if we don't have permission. + } catch (ex) { } // Do nothing since this is not a critical feature. }; // Logging funtions diff --git a/package.json b/package.json index e18b76c3..f3c030e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.2.0-q", + "version": "0.2.0-w", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/scripts/amt-terminal-0.0.2.js b/public/scripts/amt-terminal-0.0.2.js index 6bdb123a..072ce943 100644 --- a/public/scripts/amt-terminal-0.0.2.js +++ b/public/scripts/amt-terminal-0.0.2.js @@ -15,6 +15,7 @@ var CreateAmtRemoteTerminal = function (divid) { // ###END###{Terminal-Enumation-All} obj.fxEmulation = 0; obj.lineFeed = '\r\n'; + obj.debugmode = 0; obj.width = 80; // 80 or 100 obj.height = 25; // 25 or 30 @@ -53,6 +54,7 @@ var CreateAmtRemoteTerminal = function (divid) { obj.xxStateChange = function(newstate) { } obj.ProcessData = function (str) { + if (obj.debugmode == 2) { console.log("TRecv(" + str.length + "): " + rstr2hex(str)); } // ###BEGIN###{Terminal-Enumation-UTF8} //str = decode_utf8(str); // ###END###{Terminal-Enumation-UTF8} @@ -480,8 +482,8 @@ var CreateAmtRemoteTerminal = function (divid) { } } - obj.TermSendKeys = function(keys) { obj.parent.send(keys); } - obj.TermSendKey = function(key) { obj.parent.send(String.fromCharCode(key)); } + obj.TermSendKeys = function (keys) { if (obj.debugmode == 2) { if (obj.debugmode == 2) { console.log("TSend(" + keys.length + "): " + rstr2hex(keys)); } } obj.parent.send(keys); } + obj.TermSendKey = function (key) { if (obj.debugmode == 2) { if (obj.debugmode == 2) { console.log("TSend(1): " + rstr2hex(String.fromCharCode(key))); } } obj.parent.send(String.fromCharCode(key)); } function _TermMoveUp(linecount) { var x, y; diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index e9455b84..812f0f8f 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -351,7 +351,7 @@
-