mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
Improved server list view and search box.
This commit is contained in:
parent
44778d52ea
commit
a4756d572d
BIN
agents-new/MeshAgentOSXPackager.zip
Normal file
BIN
agents-new/MeshAgentOSXPackager.zip
Normal file
Binary file not shown.
BIN
agents-new/MeshCmd-signed.exe
Normal file
BIN
agents-new/MeshCmd-signed.exe
Normal file
Binary file not shown.
BIN
agents-new/MeshCmd64-signed.exe
Normal file
BIN
agents-new/MeshCmd64-signed.exe
Normal file
Binary file not shown.
BIN
agents-new/MeshCommander-Small.gz
Normal file
BIN
agents-new/MeshCommander-Small.gz
Normal file
Binary file not shown.
BIN
agents-new/MeshService-signed.exe
Normal file
BIN
agents-new/MeshService-signed.exe
Normal file
Binary file not shown.
BIN
agents-new/MeshService.exe
Normal file
BIN
agents-new/MeshService.exe
Normal file
Binary file not shown.
BIN
agents-new/MeshService64-signed.exe
Normal file
BIN
agents-new/MeshService64-signed.exe
Normal file
Binary file not shown.
BIN
agents-new/MeshService64.exe
Normal file
BIN
agents-new/MeshService64.exe
Normal file
Binary file not shown.
466
agents-new/agentrecoverycore.js
Normal file
466
agents-new/agentrecoverycore.js
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
|
||||||
|
var http = require('http');
|
||||||
|
var childProcess = require('child_process');
|
||||||
|
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore Recovery", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
||||||
|
var nextTunnelIndex = 1;
|
||||||
|
var tunnels = {};
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
//attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); });
|
||||||
|
|
||||||
|
function sendConsoleText(msg)
|
||||||
|
{
|
||||||
|
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg });
|
||||||
|
}
|
||||||
|
// Return p number of spaces
|
||||||
|
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
|
||||||
|
|
||||||
|
var path =
|
||||||
|
{
|
||||||
|
join: function ()
|
||||||
|
{
|
||||||
|
var x = [];
|
||||||
|
for (var i in arguments)
|
||||||
|
{
|
||||||
|
var w = arguments[i];
|
||||||
|
if (w != null)
|
||||||
|
{
|
||||||
|
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
|
||||||
|
}
|
||||||
|
x.push(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x.length == 0) return '/';
|
||||||
|
return x.join('/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Convert an object to string with all functions
|
||||||
|
function objToString(x, p, pad, ret) {
|
||||||
|
if (ret == undefined) ret = '';
|
||||||
|
if (p == undefined) p = 0;
|
||||||
|
if (x == null) { return '[null]'; }
|
||||||
|
if (p > 8) { return '[...]'; }
|
||||||
|
if (x == undefined) { return '[undefined]'; }
|
||||||
|
if (typeof x == 'string') { if (p == 0) return x; return '"' + x + '"'; }
|
||||||
|
if (typeof x == 'buffer') { return '[buffer]'; }
|
||||||
|
if (typeof x != 'object') { return x; }
|
||||||
|
var r = '{' + (ret ? '\r\n' : ' ');
|
||||||
|
for (var i in x) { if (i != '_ObjectID') { r += (addPad(p + 2, pad) + i + ': ' + objToString(x[i], p + 2, pad, ret) + (ret ? '\r\n' : ' ')); } }
|
||||||
|
return r + addPad(p, pad) + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split a string taking into account the quoats. Used for command line parsing
|
||||||
|
function splitArgs(str)
|
||||||
|
{
|
||||||
|
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
|
||||||
|
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
|
||||||
|
return myArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse arguments string array into an object
|
||||||
|
function parseArgs(argv)
|
||||||
|
{
|
||||||
|
var results = { '_': [] }, current = null;
|
||||||
|
for (var i = 1, len = argv.length; i < len; i++) {
|
||||||
|
var x = argv[i];
|
||||||
|
if (x.length > 2 && x[0] == '-' && x[1] == '-') {
|
||||||
|
if (current != null) { results[current] = true; }
|
||||||
|
current = x.substring(2);
|
||||||
|
} else {
|
||||||
|
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current != null) { results[current] = true; }
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
// Get server target url with a custom path
|
||||||
|
function getServerTargetUrl(path)
|
||||||
|
{
|
||||||
|
var x = require('MeshAgent').ServerUrl;
|
||||||
|
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
|
||||||
|
if (x == null) { return null; }
|
||||||
|
if (path == null) { path = ''; }
|
||||||
|
x = http.parseUri(x);
|
||||||
|
if (x == null) return null;
|
||||||
|
return x.protocol + '//' + x.host + ':' + x.port + '/' + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get server url. If the url starts with "*/..." change it, it not use the url as is.
|
||||||
|
function getServerTargetUrlEx(url)
|
||||||
|
{
|
||||||
|
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
require('MeshAgent').on('Connected', function ()
|
||||||
|
{
|
||||||
|
require('os').name().then(function (v)
|
||||||
|
{
|
||||||
|
sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
|
||||||
|
require('MeshAgent').SendCommand(meshCoreObj);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tunnel callback operations
|
||||||
|
function onTunnelUpgrade(response, s, head) {
|
||||||
|
this.s = s;
|
||||||
|
s.httprequest = this;
|
||||||
|
s.end = onTunnelClosed;
|
||||||
|
s.tunnel = this;
|
||||||
|
|
||||||
|
//sendConsoleText('onTunnelUpgrade');
|
||||||
|
|
||||||
|
if (this.tcpport != null) {
|
||||||
|
// This is a TCP relay connection, pause now and try to connect to the target.
|
||||||
|
s.pause();
|
||||||
|
s.data = onTcpRelayServerTunnelData;
|
||||||
|
var connectionOptions = { port: parseInt(this.tcpport) };
|
||||||
|
if (this.tcpaddr != null) { connectionOptions.host = this.tcpaddr; } else { connectionOptions.host = '127.0.0.1'; }
|
||||||
|
s.tcprelay = net.createConnection(connectionOptions, onTcpRelayTargetTunnelConnect);
|
||||||
|
s.tcprelay.peerindex = this.index;
|
||||||
|
} else {
|
||||||
|
// This is a normal connect for KVM/Terminal/Files
|
||||||
|
s.data = onTunnelData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require('MeshAgent').AddCommandHandler(function (data)
|
||||||
|
{
|
||||||
|
if (typeof data == 'object')
|
||||||
|
{
|
||||||
|
// If this is a console command, parse it and call the console handler
|
||||||
|
switch (data.action)
|
||||||
|
{
|
||||||
|
case 'msg':
|
||||||
|
{
|
||||||
|
switch (data.type)
|
||||||
|
{
|
||||||
|
case 'console': { // Process a console command
|
||||||
|
if (data.value && data.sessionid)
|
||||||
|
{
|
||||||
|
var args = splitArgs(data.value);
|
||||||
|
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'tunnel':
|
||||||
|
{
|
||||||
|
if (data.value != null) { // Process a new tunnel connection request
|
||||||
|
// Create a new tunnel object
|
||||||
|
var xurl = getServerTargetUrlEx(data.value);
|
||||||
|
if (xurl != null) {
|
||||||
|
var woptions = http.parseUri(xurl);
|
||||||
|
woptions.rejectUnauthorized = 0;
|
||||||
|
//sendConsoleText(JSON.stringify(woptions));
|
||||||
|
var tunnel = http.request(woptions);
|
||||||
|
tunnel.on('upgrade', function (response, s, head)
|
||||||
|
{
|
||||||
|
this.s = s;
|
||||||
|
s.httprequest = this;
|
||||||
|
s.tunnel = this;
|
||||||
|
s.on('end', function ()
|
||||||
|
{
|
||||||
|
if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
|
||||||
|
|
||||||
|
// If there is a upload or download active on this connection, close the file
|
||||||
|
if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||||
|
if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
|
||||||
|
|
||||||
|
|
||||||
|
//sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
|
||||||
|
delete tunnels[this.httprequest.index];
|
||||||
|
|
||||||
|
// Clean up WebSocket
|
||||||
|
this.removeAllListeners('data');
|
||||||
|
});
|
||||||
|
s.on('data', function (data)
|
||||||
|
{
|
||||||
|
// If this is upload data, save it to file
|
||||||
|
if (this.httprequest.uploadFile)
|
||||||
|
{
|
||||||
|
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
|
||||||
|
this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.httprequest.state == 0) {
|
||||||
|
// Check if this is a relay connection
|
||||||
|
if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
|
||||||
|
} else {
|
||||||
|
// Handle tunnel data
|
||||||
|
if (this.httprequest.protocol == 0)
|
||||||
|
{
|
||||||
|
// Take a look at the protocol
|
||||||
|
this.httprequest.protocol = parseInt(data);
|
||||||
|
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
|
||||||
|
if (this.httprequest.protocol == 1)
|
||||||
|
{
|
||||||
|
// Remote terminal using native pipes
|
||||||
|
if (process.platform == "win32")
|
||||||
|
{
|
||||||
|
this.httprequest._term = require('win-terminal').Start(80, 25);
|
||||||
|
this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
|
||||||
|
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
|
||||||
|
this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
|
||||||
|
this.httprequest.process.tunnel = this;
|
||||||
|
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
|
||||||
|
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
|
||||||
|
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||||
|
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||||
|
this.prependListener('end', function () { this.httprequest.process.kill(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on('end', function () {
|
||||||
|
if (process.platform == "win32")
|
||||||
|
{
|
||||||
|
// Unpipe the web socket
|
||||||
|
this.unpipe(this.httprequest._term);
|
||||||
|
this.httprequest._term.unpipe(this);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
this.httprequest._term.end();
|
||||||
|
this.httprequest._term = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.httprequest.protocol == 5)
|
||||||
|
{
|
||||||
|
// Process files commands
|
||||||
|
var cmd = null;
|
||||||
|
try { cmd = JSON.parse(data); } catch (e) { };
|
||||||
|
if (cmd == null) { return; }
|
||||||
|
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
|
||||||
|
if (cmd.action == undefined) { return; }
|
||||||
|
console.log('action: ', cmd.action);
|
||||||
|
|
||||||
|
//sendConsoleText('CMD: ' + JSON.stringify(cmd));
|
||||||
|
|
||||||
|
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
|
||||||
|
//console.log(objToString(cmd, 0, ' '));
|
||||||
|
switch (cmd.action)
|
||||||
|
{
|
||||||
|
case 'ls':
|
||||||
|
// Send the folder content to the browser
|
||||||
|
var response = getDirectoryInfo(cmd.path);
|
||||||
|
if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
|
||||||
|
this.write(new Buffer(JSON.stringify(response)));
|
||||||
|
break;
|
||||||
|
case 'mkdir': {
|
||||||
|
// Create a new empty folder
|
||||||
|
fs.mkdirSync(cmd.path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rm': {
|
||||||
|
// Delete, possibly recursive delete
|
||||||
|
for (var i in cmd.delfiles)
|
||||||
|
{
|
||||||
|
try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rename': {
|
||||||
|
// Rename a file or folder
|
||||||
|
var oldfullpath = path.join(cmd.path, cmd.oldname);
|
||||||
|
var newfullpath = path.join(cmd.path, cmd.newname);
|
||||||
|
try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'upload': {
|
||||||
|
// Upload a file, browser to agent
|
||||||
|
if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||||
|
if (cmd.path == undefined) break;
|
||||||
|
var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path;
|
||||||
|
try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
|
||||||
|
this.httprequest.uploadFileid = cmd.reqid;
|
||||||
|
if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'copy': {
|
||||||
|
// Copy a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'move': {
|
||||||
|
// Move a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
|
||||||
|
tunnel.sessionid = data.sessionid;
|
||||||
|
tunnel.rights = data.rights;
|
||||||
|
tunnel.state = 0;
|
||||||
|
tunnel.url = xurl;
|
||||||
|
tunnel.protocol = 0;
|
||||||
|
tunnel.tcpaddr = data.tcpaddr;
|
||||||
|
tunnel.tcpport = data.tcpport;
|
||||||
|
tunnel.end();
|
||||||
|
// Put the tunnel in the tunnels list
|
||||||
|
var index = nextTunnelIndex++;
|
||||||
|
tunnel.index = index;
|
||||||
|
tunnels[index] = tunnel;
|
||||||
|
|
||||||
|
//sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown action, ignore it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Unknown action, ignore it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function processConsoleCommand(cmd, args, rights, sessionid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = null;
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case 'help':
|
||||||
|
response = 'Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'osinfo': { // Return the operating system information
|
||||||
|
var i = 1;
|
||||||
|
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
|
||||||
|
for (var j = 0; j < i; j++) {
|
||||||
|
var pr = require('os').name();
|
||||||
|
pr.sessionid = sessionid;
|
||||||
|
pr.then(function (v) { sendConsoleText("OS: " + v, this.sessionid); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbkeys': { // Return all data store keys
|
||||||
|
response = JSON.stringify(db.Keys);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbget': { // Return the data store value for a given key
|
||||||
|
if (db == null) { response = 'Database not accessible.'; break; }
|
||||||
|
if (args['_'].length != 1) {
|
||||||
|
response = 'Proper usage: dbget (key)'; // Display the value for a given database key
|
||||||
|
} else {
|
||||||
|
response = db.Get(args['_'][0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbset': { // Set a data store key and value pair
|
||||||
|
if (db == null) { response = 'Database not accessible.'; break; }
|
||||||
|
if (args['_'].length != 2) {
|
||||||
|
response = 'Proper usage: dbset (key) (value)'; // Set a database key
|
||||||
|
} else {
|
||||||
|
var r = db.Put(args['_'][0], args['_'][1]);
|
||||||
|
response = 'Key set: ' + r;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbcompact': { // Compact the data store
|
||||||
|
if (db == null) { response = 'Database not accessible.'; break; }
|
||||||
|
var r = db.Compact();
|
||||||
|
response = 'Database compacted: ' + r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'tunnels': { // Show the list of current tunnels
|
||||||
|
response = '';
|
||||||
|
for (var i in tunnels) { response += 'Tunnel #' + i + ', ' + tunnels[i].url + '\r\n'; }
|
||||||
|
if (response == '') { response = 'No websocket sessions.'; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'netinfo': { // Show network interface information
|
||||||
|
//response = objToString(mesh.NetInfo, 0, ' ');
|
||||||
|
var interfaces = require('os').networkInterfaces();
|
||||||
|
response = objToString(interfaces, 0, ' ', true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { // This is an unknown command, return an error message
|
||||||
|
response = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); }
|
||||||
|
if (response != null) { sendConsoleText(response, sessionid); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a formated response for a given directory path
|
||||||
|
function getDirectoryInfo(reqpath)
|
||||||
|
{
|
||||||
|
var response = { path: reqpath, dir: [] };
|
||||||
|
if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
|
||||||
|
// List all the drives in the root, or the root itself
|
||||||
|
var results = null;
|
||||||
|
try { results = fs.readDrivesSync(); } catch (e) { } // TODO: Anyway to get drive total size and free space? Could draw a progress bar.
|
||||||
|
if (results != null) {
|
||||||
|
for (var i = 0; i < results.length; ++i) {
|
||||||
|
var drive = { n: results[i].name, t: 1 };
|
||||||
|
if (results[i].type == 'REMOVABLE') { drive.dt = 'removable'; } // TODO: See if this is USB/CDROM or something else, we can draw icons.
|
||||||
|
response.dir.push(drive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// List all the files and folders in this path
|
||||||
|
if (reqpath == '') { reqpath = '/'; }
|
||||||
|
var results = null, xpath = path.join(reqpath, '*');
|
||||||
|
//if (process.platform == "win32") { xpath = xpath.split('/').join('\\'); }
|
||||||
|
try { results = fs.readdirSync(xpath); } catch (e) { }
|
||||||
|
if (results != null) {
|
||||||
|
for (var i = 0; i < results.length; ++i) {
|
||||||
|
if ((results[i] != '.') && (results[i] != '..')) {
|
||||||
|
var stat = null, p = path.join(reqpath, results[i]);
|
||||||
|
//if (process.platform == "win32") { p = p.split('/').join('\\'); }
|
||||||
|
try { stat = fs.statSync(p); } catch (e) { } // TODO: Get file size/date
|
||||||
|
if ((stat != null) && (stat != undefined)) {
|
||||||
|
if (stat.isDirectory() == true) {
|
||||||
|
response.dir.push({ n: results[i], t: 2, d: stat.mtime });
|
||||||
|
} else {
|
||||||
|
response.dir.push({ n: results[i], t: 3, s: stat.size, d: stat.mtime });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
// Delete a directory with a files and directories within it
|
||||||
|
function deleteFolderRecursive(path, rec) {
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
if (rec == true) {
|
||||||
|
fs.readdirSync(path.join(path, '*')).forEach(function (file, index) {
|
||||||
|
var curPath = path.join(path, file);
|
||||||
|
if (fs.statSync(curPath).isDirectory()) { // recurse
|
||||||
|
deleteFolderRecursive(curPath, true);
|
||||||
|
} else { // delete file
|
||||||
|
fs.unlinkSync(curPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fs.unlinkSync(path);
|
||||||
|
}
|
||||||
|
};
|
7
agents-new/compressModules.bat
Normal file
7
agents-new/compressModules.bat
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
MD modules_meshcmd_min
|
||||||
|
MD modules_meshcore_min
|
||||||
|
"..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe" compressalljs "modules_meshcore" "modules_meshcore_min"
|
||||||
|
"..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe" compressalljs "modules_meshcmd" "modules_meshcmd_min"
|
||||||
|
"..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe" meshcore.js
|
||||||
|
"..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe" meshcmd.js
|
7
agents-new/compressRemove.bat
Normal file
7
agents-new/compressRemove.bat
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
DEL meshcmd.min.js
|
||||||
|
DEL meshcore.min.js
|
||||||
|
DEL modules_meshcmd_min\*.min.js
|
||||||
|
DEL modules_meshcore_min\*.min.js
|
||||||
|
RD modules_meshcmd_min
|
||||||
|
RD modules_meshcore_min
|
BIN
agents-new/meshagent_arm
Normal file
BIN
agents-new/meshagent_arm
Normal file
Binary file not shown.
BIN
agents-new/meshagent_arm-linaro
Normal file
BIN
agents-new/meshagent_arm-linaro
Normal file
Binary file not shown.
BIN
agents-new/meshagent_armhf
Normal file
BIN
agents-new/meshagent_armhf
Normal file
Binary file not shown.
BIN
agents-new/meshagent_mips
Normal file
BIN
agents-new/meshagent_mips
Normal file
Binary file not shown.
BIN
agents-new/meshagent_osx-x86-64
Normal file
BIN
agents-new/meshagent_osx-x86-64
Normal file
Binary file not shown.
BIN
agents-new/meshagent_pogo
Normal file
BIN
agents-new/meshagent_pogo
Normal file
Binary file not shown.
BIN
agents-new/meshagent_poky
Normal file
BIN
agents-new/meshagent_poky
Normal file
Binary file not shown.
BIN
agents-new/meshagent_poky64
Normal file
BIN
agents-new/meshagent_poky64
Normal file
Binary file not shown.
BIN
agents-new/meshagent_x86
Normal file
BIN
agents-new/meshagent_x86
Normal file
Binary file not shown.
BIN
agents-new/meshagent_x86-64
Normal file
BIN
agents-new/meshagent_x86-64
Normal file
Binary file not shown.
BIN
agents-new/meshagent_x86-64_nokvm
Normal file
BIN
agents-new/meshagent_x86-64_nokvm
Normal file
Binary file not shown.
BIN
agents-new/meshagent_x86_nokvm
Normal file
BIN
agents-new/meshagent_x86_nokvm
Normal file
Binary file not shown.
1604
agents-new/meshcmd.js
Normal file
1604
agents-new/meshcmd.js
Normal file
File diff suppressed because one or more lines are too long
1761
agents-new/meshcore-old.js
Normal file
1761
agents-new/meshcore-old.js
Normal file
File diff suppressed because it is too large
Load Diff
1776
agents-new/meshcore.js
Normal file
1776
agents-new/meshcore.js
Normal file
File diff suppressed because it is too large
Load Diff
82
agents-new/meshinstall-initd.sh
Normal file
82
agents-new/meshinstall-initd.sh
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: <NAME>
|
||||||
|
# Required-Start: $local_fs $network $named $time $syslog
|
||||||
|
# Required-Stop: $local_fs $network $named $time $syslog
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Description: <DESCRIPTION>
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
SCRIPT=/usr/local/mesh/meshagent
|
||||||
|
RUNAS=root
|
||||||
|
|
||||||
|
PIDFILE=/var/run/meshagent.pid
|
||||||
|
LOGFILE=/var/log/meshagent.log
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") 2>/dev/null; then
|
||||||
|
echo 'Service already running' >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo 'Starting service…' >&2
|
||||||
|
local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
|
||||||
|
su -c "$CMD" $RUNAS > "$PIDFILE"
|
||||||
|
echo 'Service started' >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if [ ! -f "$PIDFILE" ]; then
|
||||||
|
echo 'Service not running' >&2
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
pid=$( cat "$PIDFILE" )
|
||||||
|
if kill -0 $pid 2>/dev/null; then
|
||||||
|
echo 'Stopping service…' >&2
|
||||||
|
kill -16 $pid
|
||||||
|
echo 'Service stopped' >&2
|
||||||
|
else
|
||||||
|
echo 'Service not running'
|
||||||
|
fi
|
||||||
|
rm -f $"PIDFILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
restart(){
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
}
|
||||||
|
status(){
|
||||||
|
if [ -f "$PIDFILE" ]
|
||||||
|
then
|
||||||
|
pid=$( cat "$PIDFILE" )
|
||||||
|
if kill -0 $pid 2>/dev/null; then
|
||||||
|
echo "meshagent start/running, process $pid"
|
||||||
|
else
|
||||||
|
echo 'meshagent stop/waiting'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo 'meshagent stop/waiting'
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: service meshagent {start|stop|restart|status}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit 0
|
235
agents-new/meshinstall-linux.sh
Normal file
235
agents-new/meshinstall-linux.sh
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CheckStartupType() {
|
||||||
|
# echo "Checking process autostart system..."
|
||||||
|
starttype=`ps -p 1 | awk '/1/ {print $4}'`
|
||||||
|
# Systemd
|
||||||
|
if [[ $starttype == 'systemd' ]]; then return 1;
|
||||||
|
elif [[ $starttype == 'init' ]];
|
||||||
|
then
|
||||||
|
# Upstart
|
||||||
|
if [[ `/sbin/init --version` =~ upstart ]]; then return 2;
|
||||||
|
# Sysv-init
|
||||||
|
return 3;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add "StartupType=(type)" to .msh file
|
||||||
|
UpdateMshFile() {
|
||||||
|
# Remove all lines that start with "StartupType="
|
||||||
|
sed '/^StartupType=/ d' < /usr/local/mesh/meshagent.msh >> /usr/local/mesh/meshagent2.msh
|
||||||
|
# Add the startup type to the file
|
||||||
|
echo "StartupType=$starttype" >> /usr/local/mesh/meshagent2.msh
|
||||||
|
mv /usr/local/mesh/meshagent2.msh /usr/local/mesh/meshagent.msh
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckInstallAgent() {
|
||||||
|
# echo "Checking mesh identifier..."
|
||||||
|
if [ -e "/usr/local" ]
|
||||||
|
then
|
||||||
|
installpath="/usr/local/mesh"
|
||||||
|
else
|
||||||
|
installpath="/usr/mesh"
|
||||||
|
fi
|
||||||
|
if [ $# -ge 2 ]
|
||||||
|
then
|
||||||
|
url=$1
|
||||||
|
meshid=$2
|
||||||
|
meshidlen=${#meshid}
|
||||||
|
if [ $meshidlen -eq 64 ]
|
||||||
|
then
|
||||||
|
machineid=0
|
||||||
|
machinetype=$( uname -m )
|
||||||
|
|
||||||
|
# If we have 3 arguments...
|
||||||
|
if [ $# -ge 3 ]
|
||||||
|
then
|
||||||
|
# echo "Computer type is specified..."
|
||||||
|
machineid=$3
|
||||||
|
else
|
||||||
|
# echo "Detecting computer type..."
|
||||||
|
if [ $machinetype == 'x86_64' ] || [ $machinetype == 'amd64' ]
|
||||||
|
then
|
||||||
|
# Linux x86, 64 bit
|
||||||
|
machineid=6
|
||||||
|
fi
|
||||||
|
if [ $machinetype == 'x86' ] || [ $machinetype == 'i686' ] || [ $machinetype == 'i586' ]
|
||||||
|
then
|
||||||
|
# Linux x86, 32 bit
|
||||||
|
machineid=5
|
||||||
|
fi
|
||||||
|
if [ $machinetype == 'armv6l' ] || [ $machinetype == 'armv7l' ]
|
||||||
|
then
|
||||||
|
# RaspberryPi 1 (armv6l) or RaspberryPi 2/3 (armv7l)
|
||||||
|
machineid=25
|
||||||
|
fi
|
||||||
|
# Add more machine types, detect KVM support... here.
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $machineid -eq 0 ]
|
||||||
|
then
|
||||||
|
echo "Unsupported machine type: $machinetype."
|
||||||
|
else
|
||||||
|
DownloadAgent $url $meshid $machineid
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "MeshID is not correct, must be 64 characters long."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "URI and/or MeshID have not been specified, must be passed in as arguments."
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadAgent() {
|
||||||
|
url=$1
|
||||||
|
meshid=$2
|
||||||
|
machineid=$3
|
||||||
|
# Create folder
|
||||||
|
mkdir -p /usr/local/mesh
|
||||||
|
cd /usr/local/mesh
|
||||||
|
echo "Downloading Mesh agent #$machineid..."
|
||||||
|
wget $url/meshagents?id=$machineid --no-check-certificate {{{noproxy}}}-O /usr/local/mesh/meshagent
|
||||||
|
|
||||||
|
# If it did not work, try again using http
|
||||||
|
if [ $? != 0 ]
|
||||||
|
then
|
||||||
|
url=${url/"https://"/"http://"}
|
||||||
|
wget $url/meshagents?id=$machineid {{{noproxy}}}-O /usr/local/mesh/meshagent
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
echo "Mesh agent downloaded."
|
||||||
|
# TODO: We could check the meshagent sha256 hash, but best to authenticate the server.
|
||||||
|
chmod 755 /usr/local/mesh/meshagent
|
||||||
|
wget $url/meshsettings?id=$meshid --no-check-certificate {{{noproxy}}}-O /usr/local/mesh/meshagent.msh
|
||||||
|
|
||||||
|
# If it did not work, try again using http
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
wget $url/meshsettings?id=$meshid {{{noproxy}}}-O /usr/local/mesh/meshagent.msh
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
UpdateMshFile
|
||||||
|
if [ $starttype -eq 1 ]
|
||||||
|
then
|
||||||
|
# systemd
|
||||||
|
if [ -d "/lib/systemd/system/" ]
|
||||||
|
then
|
||||||
|
echo -e "[Unit]\nDescription=MeshCentral Agent\n[Service]\nExecStart=/usr/local/mesh/meshagent\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=meshagent.service\n" > /lib/systemd/system/meshagent.service
|
||||||
|
else
|
||||||
|
# Some distros have the systemd folder at a different place
|
||||||
|
if [ -d "/usr/lib/systemd/system/" ]
|
||||||
|
then
|
||||||
|
echo -e "[Unit]\nDescription=MeshCentral Agent\n[Service]\nExecStart=/usr/local/mesh/meshagent\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=meshagent.service\n" > /usr/lib/systemd/system/meshagent.service
|
||||||
|
else
|
||||||
|
echo "Unable to find systemd folder."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
systemctl enable meshagent
|
||||||
|
systemctl start meshagent
|
||||||
|
echo 'meshagent installed as systemd service.'
|
||||||
|
echo 'To start service: sudo systemctl start meshagent'
|
||||||
|
echo 'To stop service: sudo systemctl stop meshagent'
|
||||||
|
elif [ $starttype -eq 3 ]
|
||||||
|
then
|
||||||
|
# initd
|
||||||
|
wget $url/meshagents?script=2 --no-check-certificate {{{noproxy}}}-O /etc/init.d/meshagent
|
||||||
|
chmod +x /etc/init.d/meshagent
|
||||||
|
# creates symlinks for rc.d
|
||||||
|
update-rc.d meshagent defaults
|
||||||
|
service meshagent start
|
||||||
|
echo 'meshagent installed as init.d service.'
|
||||||
|
echo 'To start service: sudo service meshagent start'
|
||||||
|
echo 'To stop service: sudo service meshagent stop'
|
||||||
|
elif [ $starttype -eq 2 ]
|
||||||
|
then
|
||||||
|
# upstart
|
||||||
|
echo -e "start on runlevel [2345]\nstop on runlevel [016]\n\nrespawn\n\nchdir /usr/local/mesh\nexec /usr/local/mesh/meshagent\n\n" > /etc/init/meshagent.conf
|
||||||
|
service meshagent start
|
||||||
|
echo 'meshagent installed as upstart/init.d service.'
|
||||||
|
echo 'To start service: sudo initctl start meshagent'
|
||||||
|
echo 'To stop service: sudo initctl stop meshagent'
|
||||||
|
else
|
||||||
|
# unknown
|
||||||
|
echo "Unknown Service Platform Type. (ie: init, systemd, etc)"
|
||||||
|
echo "Unable to install meshagent as service."
|
||||||
|
fi
|
||||||
|
echo "Mesh agent started."
|
||||||
|
else
|
||||||
|
echo "Unable to download mesh settings at: $url/meshsettings?id=$meshid."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Unable to download mesh agent at: $url/meshagents?id=$machineid."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
UninstallAgent() {
|
||||||
|
# Uninstall agent
|
||||||
|
if [ -e "/usr/local" ]
|
||||||
|
then
|
||||||
|
installpath="/usr/local/mesh"
|
||||||
|
else
|
||||||
|
installpath="/usr/mesh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $starttype -eq 1 ]
|
||||||
|
then
|
||||||
|
# systemd
|
||||||
|
rm -f /sbin/meshcmd /lib/systemd/system/meshagent.service
|
||||||
|
systemctl disable meshagent
|
||||||
|
systemctl stop meshagent
|
||||||
|
else
|
||||||
|
if [ $starttype -eq 3 ]; then
|
||||||
|
# initd
|
||||||
|
service meshagent stop
|
||||||
|
update-rc.d -f meshagent remove
|
||||||
|
rm -f /sbin/meshcmd /etc/init.d/meshagent
|
||||||
|
elif [ $starttype -eq 2 ]; then
|
||||||
|
# upstart
|
||||||
|
service meshagent stop
|
||||||
|
rm -f /sbin/meshcmd
|
||||||
|
rm -f /etc/init/meshagent.conf
|
||||||
|
rm -f /etc/rc2.d/S20mesh /etc/rc3.d/S20mesh /etc/rc5.d/S20mesh
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e $installpath ]
|
||||||
|
then
|
||||||
|
rm -rf $installpath/*
|
||||||
|
rmdir $installpath
|
||||||
|
fi
|
||||||
|
echo "Agent uninstalled."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CheckStartupType
|
||||||
|
starttype=$?
|
||||||
|
#echo "Type: $starttype"
|
||||||
|
|
||||||
|
currentuser=$( whoami )
|
||||||
|
if [ $currentuser == 'root' ]
|
||||||
|
then
|
||||||
|
if [ $# -eq 0 ]
|
||||||
|
then
|
||||||
|
echo -e "This script will install or uninstall a mesh agent, usage:\n $0 [serverurl] [meshid] (machineid)\n $0 uninstall"
|
||||||
|
else
|
||||||
|
if [ $# -eq 1 ]
|
||||||
|
then
|
||||||
|
if [ $1 == 'uninstall' ] || [ $1 == 'UNINSTALL' ]
|
||||||
|
then
|
||||||
|
UninstallAgent
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
CheckInstallAgent $1 $2 $3
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Must be root to install or uninstall mesh agent."
|
||||||
|
fi
|
895
agents-new/modules_meshcmd/amt-lme.js
Normal file
895
agents-new/modules_meshcmd/amt-lme.js
Normal file
@ -0,0 +1,895 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var 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.
|
||||||
|
var xmlParser = require('amt-xml');
|
||||||
|
|
||||||
|
// Documented in: https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/HTMLDocuments/MPSDocuments/Intel%20AMT%20Port%20Forwarding%20Protocol%20Reference%20Manual.pdf
|
||||||
|
var APF_DISCONNECT = 1;
|
||||||
|
var APF_SERVICE_REQUEST = 5;
|
||||||
|
var APF_SERVICE_ACCEPT = 6;
|
||||||
|
var APF_USERAUTH_REQUEST = 50;
|
||||||
|
var APF_USERAUTH_FAILURE = 51;
|
||||||
|
var APF_USERAUTH_SUCCESS = 52;
|
||||||
|
var APF_GLOBAL_REQUEST = 80;
|
||||||
|
var APF_REQUEST_SUCCESS = 81;
|
||||||
|
var APF_REQUEST_FAILURE = 82;
|
||||||
|
var APF_CHANNEL_OPEN = 90;
|
||||||
|
var APF_CHANNEL_OPEN_CONFIRMATION = 91;
|
||||||
|
var APF_CHANNEL_OPEN_FAILURE = 92;
|
||||||
|
var APF_CHANNEL_WINDOW_ADJUST = 93;
|
||||||
|
var APF_CHANNEL_DATA = 94;
|
||||||
|
var APF_CHANNEL_CLOSE = 97;
|
||||||
|
var APF_PROTOCOLVERSION = 192;
|
||||||
|
|
||||||
|
|
||||||
|
function lme_object() {
|
||||||
|
this.ourId = ++lme_id;
|
||||||
|
this.amtId = -1;
|
||||||
|
this.LME_CHANNEL_STATUS = 'LME_CS_FREE';
|
||||||
|
this.txWindow = 0;
|
||||||
|
this.rxWindow = 0;
|
||||||
|
this.localPort = 0;
|
||||||
|
this.errorCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stream_bufferedWrite() {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
this.buffer = [];
|
||||||
|
this._readCheckImmediate = undefined;
|
||||||
|
this._ObjectID = "bufferedWriteStream";
|
||||||
|
// Writable Events
|
||||||
|
emitterUtils.createEvent('close');
|
||||||
|
emitterUtils.createEvent('drain');
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
emitterUtils.createEvent('finish');
|
||||||
|
emitterUtils.createEvent('pipe');
|
||||||
|
emitterUtils.createEvent('unpipe');
|
||||||
|
|
||||||
|
// Readable Events
|
||||||
|
emitterUtils.createEvent('readable');
|
||||||
|
this.isEmpty = function () {
|
||||||
|
return (this.buffer.length == 0);
|
||||||
|
};
|
||||||
|
this.isWaiting = function () {
|
||||||
|
return (this._readCheckImmediate == undefined);
|
||||||
|
};
|
||||||
|
this.write = function (chunk) {
|
||||||
|
for (var args in arguments) { if (typeof (arguments[args]) == 'function') { this.once('drain', arguments[args]); break; } }
|
||||||
|
var tmp = Buffer.alloc(chunk.length);
|
||||||
|
chunk.copy(tmp);
|
||||||
|
this.buffer.push({ offset: 0, data: tmp });
|
||||||
|
this.emit('readable');
|
||||||
|
return (this.buffer.length == 0 ? true : false);
|
||||||
|
};
|
||||||
|
this.read = function () {
|
||||||
|
var size = arguments.length == 0 ? undefined : arguments[0];
|
||||||
|
var bytesRead = 0;
|
||||||
|
var list = [];
|
||||||
|
while ((size == undefined || bytesRead < size) && this.buffer.length > 0) {
|
||||||
|
var len = this.buffer[0].data.length - this.buffer[0].offset;
|
||||||
|
var offset = this.buffer[0].offset;
|
||||||
|
|
||||||
|
if (len > (size - bytesRead)) {
|
||||||
|
// Only reading a subset
|
||||||
|
list.push(this.buffer[0].data.slice(offset, offset + size - bytesRead));
|
||||||
|
this.buffer[0].offset += (size - bytesRead);
|
||||||
|
bytesRead += (size - bytesRead);
|
||||||
|
} else {
|
||||||
|
// Reading the entire thing
|
||||||
|
list.push(this.buffer[0].data.slice(offset));
|
||||||
|
bytesRead += len;
|
||||||
|
this.buffer.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._readCheckImmediate = setImmediate(function (buffered) {
|
||||||
|
buffered._readCheckImmediate = undefined;
|
||||||
|
if (buffered.buffer.length == 0) {
|
||||||
|
buffered.emit('drain'); // Drained
|
||||||
|
} else {
|
||||||
|
buffered.emit('readable'); // Not drained
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
return (Buffer.concat(list));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function lme_heci(options) {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
emitterUtils.createEvent('connect');
|
||||||
|
emitterUtils.createEvent('notify');
|
||||||
|
emitterUtils.createEvent('bind');
|
||||||
|
|
||||||
|
if ((options != null) && (options.debug == true)) { lme_port_offset = -100; } // LMS debug mode
|
||||||
|
|
||||||
|
var heci = require('heci');
|
||||||
|
this.INITIAL_RXWINDOW_SIZE = 4096;
|
||||||
|
|
||||||
|
this._ObjectID = "lme";
|
||||||
|
this._LME = heci.create();
|
||||||
|
this._LME._binded = {};
|
||||||
|
this._LME.LMS = this;
|
||||||
|
this._LME.on('error', function (e) { this.LMS.emit('error', e); });
|
||||||
|
this._LME.on('connect', function () {
|
||||||
|
this.on('data', function (chunk) {
|
||||||
|
// this = HECI
|
||||||
|
var cmd = chunk.readUInt8(0);
|
||||||
|
//console.log('LME Command ' + cmd + ', ' + chunk.length + ' byte(s).');
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
default:
|
||||||
|
console.log('Unhandled LME Command ' + cmd + ', ' + chunk.length + ' byte(s).');
|
||||||
|
break;
|
||||||
|
case APF_SERVICE_REQUEST:
|
||||||
|
var nameLen = chunk.readUInt32BE(1);
|
||||||
|
var name = chunk.slice(5, nameLen + 5);
|
||||||
|
//console.log("Service Request for: " + name);
|
||||||
|
if (name == 'pfwd@amt.intel.com' || name == 'auth@amt.intel.com') {
|
||||||
|
var outBuffer = Buffer.alloc(5 + nameLen);
|
||||||
|
outBuffer.writeUInt8(6, 0);
|
||||||
|
outBuffer.writeUInt32BE(nameLen, 1);
|
||||||
|
outBuffer.write(name.toString(), 5);
|
||||||
|
this.write(outBuffer);
|
||||||
|
//console.log('Answering APF_SERVICE_REQUEST');
|
||||||
|
} else {
|
||||||
|
//console.log('UNKNOWN APF_SERVICE_REQUEST');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_GLOBAL_REQUEST:
|
||||||
|
var nameLen = chunk.readUInt32BE(1);
|
||||||
|
var name = chunk.slice(5, nameLen + 5).toString();
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case 'tcpip-forward':
|
||||||
|
var len = chunk.readUInt32BE(nameLen + 6);
|
||||||
|
var port = chunk.readUInt32BE(nameLen + 10 + len);
|
||||||
|
//console.log("[" + chunk.length + "/" + len + "] APF_GLOBAL_REQUEST for: " + name + " on port " + port);
|
||||||
|
if (this[name] == undefined) { this[name] = {}; }
|
||||||
|
if (this[name][port] != null) { // Close the existing binding
|
||||||
|
for (var i in this.sockets) {
|
||||||
|
var channel = this.sockets[i];
|
||||||
|
if (channel.localPort == port) { this.sockets[i].end(); delete this.sockets[i]; } // Close this socket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this[name][port] == null)
|
||||||
|
{ // Bind a new server socket if not already present
|
||||||
|
this[name][port] = require('net').createServer();
|
||||||
|
this[name][port].HECI = this;
|
||||||
|
if (lme_port_offset == 0) {
|
||||||
|
this[name][port].listen({ port: port, host: '127.0.0.1' }); // Normal mode
|
||||||
|
} else {
|
||||||
|
this[name][port].listen({ port: (port + lme_port_offset) }); // Debug mode
|
||||||
|
}
|
||||||
|
this[name][port].on('connection', function (socket) {
|
||||||
|
//console.log('New [' + socket.remoteFamily + '] TCP Connection on: ' + socket.remoteAddress + ' :' + socket.localPort);
|
||||||
|
this.HECI.LMS.bindDuplexStream(socket, socket.remoteFamily, socket.localPort - lme_port_offset);
|
||||||
|
});
|
||||||
|
this._binded[port] = true;
|
||||||
|
this.LMS.emit('bind', this._binded);
|
||||||
|
}
|
||||||
|
var outBuffer = Buffer.alloc(5);
|
||||||
|
outBuffer.writeUInt8(81, 0);
|
||||||
|
outBuffer.writeUInt32BE(port, 1);
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
case 'cancel-tcpip-forward':
|
||||||
|
var outBuffer = Buffer.alloc(1);
|
||||||
|
outBuffer.writeUInt8(APF_REQUEST_SUCCESS, 0);
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
case 'udp-send-to@amt.intel.com':
|
||||||
|
var outBuffer = Buffer.alloc(1);
|
||||||
|
outBuffer.writeUInt8(APF_REQUEST_FAILURE, 0);
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//console.log("Unknown APF_GLOBAL_REQUEST for: " + name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_OPEN_CONFIRMATION:
|
||||||
|
var rChannel = chunk.readUInt32BE(1);
|
||||||
|
var sChannel = chunk.readUInt32BE(5);
|
||||||
|
var wSize = chunk.readUInt32BE(9);
|
||||||
|
//console.log('rChannel/' + rChannel + ', sChannel/' + sChannel + ', wSize/' + wSize);
|
||||||
|
if (this.sockets[rChannel] != undefined) {
|
||||||
|
this.sockets[rChannel].lme.amtId = sChannel;
|
||||||
|
this.sockets[rChannel].lme.rxWindow = wSize;
|
||||||
|
this.sockets[rChannel].lme.txWindow = wSize;
|
||||||
|
this.sockets[rChannel].lme.LME_CHANNEL_STATUS = 'LME_CS_CONNECTED';
|
||||||
|
//console.log('LME_CS_CONNECTED');
|
||||||
|
this.sockets[rChannel].bufferedStream = new stream_bufferedWrite();
|
||||||
|
this.sockets[rChannel].bufferedStream.socket = this.sockets[rChannel];
|
||||||
|
this.sockets[rChannel].bufferedStream.on('readable', function () {
|
||||||
|
if (this.socket.lme.txWindow > 0) {
|
||||||
|
var buffer = this.read(this.socket.lme.txWindow);
|
||||||
|
var packet = Buffer.alloc(9 + buffer.length);
|
||||||
|
packet.writeUInt8(APF_CHANNEL_DATA, 0);
|
||||||
|
packet.writeUInt32BE(this.socket.lme.amtId, 1);
|
||||||
|
packet.writeUInt32BE(buffer.length, 5);
|
||||||
|
buffer.copy(packet, 9);
|
||||||
|
this.socket.lme.txWindow -= buffer.length;
|
||||||
|
this.socket.HECI.write(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].bufferedStream.on('drain', function () {
|
||||||
|
this.socket.resume();
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].on('data', function (chunk) {
|
||||||
|
if (!this.bufferedStream.write(chunk)) { this.pause(); }
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].on('end', function () {
|
||||||
|
var outBuffer = Buffer.alloc(5);
|
||||||
|
outBuffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
|
||||||
|
outBuffer.writeUInt32BE(this.lme.amtId, 1);
|
||||||
|
this.HECI.write(outBuffer);
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case APF_PROTOCOLVERSION:
|
||||||
|
var major = chunk.readUInt32BE(1);
|
||||||
|
var minor = chunk.readUInt32BE(5);
|
||||||
|
var reason = chunk.readUInt32BE(9);
|
||||||
|
var outBuffer = Buffer.alloc(93);
|
||||||
|
outBuffer.writeUInt8(192, 0);
|
||||||
|
outBuffer.writeUInt32BE(1, 1);
|
||||||
|
outBuffer.writeUInt32BE(0, 5);
|
||||||
|
outBuffer.writeUInt32BE(reason, 9);
|
||||||
|
//console.log('Answering PROTOCOL_VERSION');
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_WINDOW_ADJUST:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
var bytesToAdd = chunk.readUInt32BE(5);
|
||||||
|
if (this.sockets[rChannelId] != undefined) {
|
||||||
|
this.sockets[rChannelId].lme.txWindow += bytesToAdd;
|
||||||
|
if (!this.sockets[rChannelId].bufferedStream.isEmpty() && this.sockets[rChannelId].bufferedStream.isWaiting()) {
|
||||||
|
this.sockets[rChannelId].bufferedStream.emit('readable');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_DATA:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
var dataLen = chunk.readUInt32BE(5);
|
||||||
|
var data = chunk.slice(9, 9 + dataLen);
|
||||||
|
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
|
||||||
|
this.sockets[rChannelId].pendingBytes.push(data.length);
|
||||||
|
this.sockets[rChannelId].write(data, function () {
|
||||||
|
var written = this.pendingBytes.shift();
|
||||||
|
//console.log('adjust', this.lme.amtId, written);
|
||||||
|
var outBuffer = Buffer.alloc(9);
|
||||||
|
outBuffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
|
||||||
|
outBuffer.writeUInt32BE(this.lme.amtId, 1);
|
||||||
|
outBuffer.writeUInt32BE(written, 5);
|
||||||
|
this.HECI.write(outBuffer);
|
||||||
|
});
|
||||||
|
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
|
||||||
|
var channel = this.insockets[rChannelId];
|
||||||
|
if (channel.data == null) { channel.data = data.toString(); } else { channel.data += data.toString(); }
|
||||||
|
channel.rxWindow += dataLen;
|
||||||
|
//console.log('IN DATA', channel.rxWindow, channel.data.length, dataLen, channel.amtId, data.toString());
|
||||||
|
var httpData = parseHttp(channel.data);
|
||||||
|
if ((httpData != null) || (channel.data.length >= 8000)) {
|
||||||
|
// Parse the WSMAN
|
||||||
|
var notify = null;
|
||||||
|
try { notify = xmlParser.ParseWsman(httpData); } catch (e) { }
|
||||||
|
|
||||||
|
// Event the http data
|
||||||
|
if (notify != null) { this.LMS.emit('notify', notify, channel.options, _lmsNotifyToString(notify), _lmsNotifyToCode(notify)); }
|
||||||
|
|
||||||
|
// Send channel close
|
||||||
|
var buffer = Buffer.alloc(5);
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
|
||||||
|
buffer.writeUInt32BE(amtId, 1);
|
||||||
|
this.write(buffer);
|
||||||
|
} else {
|
||||||
|
if (channel.rxWindow > 6000) {
|
||||||
|
// Send window adjust
|
||||||
|
var buffer = Buffer.alloc(9);
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
|
||||||
|
buffer.writeUInt32BE(channel.amtId, 1);
|
||||||
|
buffer.writeUInt32BE(channel.rxWindow, 5);
|
||||||
|
this.write(buffer);
|
||||||
|
channel.rxWindow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_OPEN_FAILURE:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
var reasonCode = chunk.readUInt32BE(5);
|
||||||
|
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
|
||||||
|
this.sockets[rChannelId].end();
|
||||||
|
delete this.sockets[rChannelId];
|
||||||
|
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
|
||||||
|
delete this.insockets[rChannelId];
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_OPEN_FAILURE');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_CLOSE:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
|
||||||
|
this.sockets[rChannelId].end();
|
||||||
|
var amtId = this.sockets[rChannelId].lme.amtId;
|
||||||
|
var buffer = Buffer.alloc(5);
|
||||||
|
delete this.sockets[rChannelId];
|
||||||
|
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0); // ????????????????????????????
|
||||||
|
buffer.writeUInt32BE(amtId, 1);
|
||||||
|
this.write(buffer);
|
||||||
|
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
|
||||||
|
delete this.insockets[rChannelId];
|
||||||
|
// Should I send a close back????
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_CLOSE');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_OPEN:
|
||||||
|
var nameLen = chunk.readUInt32BE(1);
|
||||||
|
var name = chunk.slice(5, nameLen + 5).toString();
|
||||||
|
var channelSender = chunk.readUInt32BE(nameLen + 5);
|
||||||
|
var initialWindowSize = chunk.readUInt32BE(nameLen + 9);
|
||||||
|
var hostToConnectLen = chunk.readUInt32BE(nameLen + 17);
|
||||||
|
var hostToConnect = chunk.slice(nameLen + 21, nameLen + 21 + hostToConnectLen).toString();
|
||||||
|
var portToConnect = chunk.readUInt32BE(nameLen + 21 + hostToConnectLen);
|
||||||
|
var originatorIpLen = chunk.readUInt32BE(nameLen + 25 + hostToConnectLen);
|
||||||
|
var originatorIp = chunk.slice(nameLen + 29 + hostToConnectLen, nameLen + 29 + hostToConnectLen + originatorIpLen).toString();
|
||||||
|
var originatorPort = chunk.readUInt32BE(nameLen + 29 + hostToConnectLen + originatorIpLen);
|
||||||
|
//console.log('APF_CHANNEL_OPEN', name, channelSender, initialWindowSize, 'From: ' + originatorIp + ':' + originatorPort, 'To: ' + hostToConnect + ':' + portToConnect);
|
||||||
|
|
||||||
|
if (this.insockets == null) { this.insockets = {}; }
|
||||||
|
var ourId = ++lme_id;
|
||||||
|
var insocket = new lme_object();
|
||||||
|
insocket.ourId = ourId;
|
||||||
|
insocket.amtId = channelSender;
|
||||||
|
insocket.txWindow = initialWindowSize;
|
||||||
|
insocket.rxWindow = 0;
|
||||||
|
insocket.options = { target: hostToConnect, targetPort: portToConnect, source: originatorIp, sourcePort: originatorPort };
|
||||||
|
this.insockets[ourId] = insocket;
|
||||||
|
|
||||||
|
var buffer = Buffer.alloc(17);
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_OPEN_CONFIRMATION, 0);
|
||||||
|
buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel
|
||||||
|
buffer.writeUInt32BE(ourId, 5); // Our receiver channel id
|
||||||
|
buffer.writeUInt32BE(4000, 9); // Initial Window Size
|
||||||
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.LMS.emit('connect');
|
||||||
|
this.resume();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bindDuplexStream = function (duplexStream, remoteFamily, localPort) {
|
||||||
|
var socket = duplexStream;
|
||||||
|
//console.log('New [' + remoteFamily + '] Virtual Connection/' + socket.localPort);
|
||||||
|
socket.pendingBytes = [];
|
||||||
|
socket.HECI = this._LME;
|
||||||
|
socket.LMS = this;
|
||||||
|
socket.lme = new lme_object();
|
||||||
|
socket.lme.Socket = socket;
|
||||||
|
socket.localPort = localPort;
|
||||||
|
var buffer = new MemoryStream();
|
||||||
|
buffer.writeUInt8(0x5A);
|
||||||
|
buffer.writeUInt32BE(15);
|
||||||
|
buffer.write('forwarded-tcpip');
|
||||||
|
buffer.writeUInt32BE(socket.lme.ourId);
|
||||||
|
buffer.writeUInt32BE(this.INITIAL_RXWINDOW_SIZE);
|
||||||
|
buffer.writeUInt32BE(0xFFFFFFFF);
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
if (remoteFamily == 'IPv6') {
|
||||||
|
buffer.writeUInt32BE(3);
|
||||||
|
buffer.write('::1');
|
||||||
|
} else {
|
||||||
|
buffer.writeUInt32BE(9);
|
||||||
|
buffer.write('127.0.0.1');
|
||||||
|
}
|
||||||
|
buffer.writeUInt32BE(localPort);
|
||||||
|
}
|
||||||
|
this._LME.write(buffer.buffer);
|
||||||
|
if (this._LME.sockets == undefined) { this._LME.sockets = {}; }
|
||||||
|
this._LME.sockets[socket.lme.ourId] = socket;
|
||||||
|
socket.pause();
|
||||||
|
};
|
||||||
|
|
||||||
|
this._LME.connect(heci.GUIDS.LME, { noPipeline: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseHttp(httpData) {
|
||||||
|
var i = httpData.indexOf('\r\n\r\n');
|
||||||
|
if ((i == -1) || (httpData.length < (i + 2))) { return null; }
|
||||||
|
var headers = require('http-headers')(httpData.substring(0, i), true);
|
||||||
|
var contentLength = parseInt(headers['content-length']);
|
||||||
|
if (httpData.length >= contentLength + i + 4) { return httpData.substring(i + 4, i + 4 + contentLength); }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lmsNotifyToCode(notify) {
|
||||||
|
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
|
||||||
|
var msgid = notify.Body.MessageID;
|
||||||
|
try { msgid += '-' + notify.Body.MessageArguments[0]; } catch (e) { }
|
||||||
|
return msgid;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lmsNotifyToString(notify) {
|
||||||
|
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
|
||||||
|
var msgid = notify.Body.MessageID;
|
||||||
|
try { msgid += '-' + notify.Body.MessageArguments[0]; } catch (e) { }
|
||||||
|
if (lmsEvents[msgid]) { return lmsEvents[msgid]; }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lmsEvents = {
|
||||||
|
"iAMT0001": "System Defense Policy %1s triggered.",
|
||||||
|
"iAMT0002": "Agent Presence Agent %1s not started.",
|
||||||
|
"iAMT0003": "Agent Presence Agent %1s stopped.",
|
||||||
|
"iAMT0004": "Agent Presence Agent %1s running.",
|
||||||
|
"iAMT0005": "Agent Presence Agent %1s expired.",
|
||||||
|
"iAMT0006": "Agent Presence Agent %1s suspended.",
|
||||||
|
"iAMT0007": "Host software attempt to disable AMT Network link detected.",
|
||||||
|
"iAMT0008": "Host software attempt to disable AMT Network link detected -- Host Network link blocked.",
|
||||||
|
"iAMT0009": "AMT clock or FLASH wear-out protection disabled.",
|
||||||
|
"iAMT0010": "Intel(R) AMT Network Interface %1s heuristics defense slow threshold trespassed.",
|
||||||
|
"iAMT0011": "Intel(R) AMT Network Interface %1s heuristics defense fast threshold trespassed.",
|
||||||
|
"iAMT0012": "Intel(R) AMT Network Interface %1s heuristics defense factory defined threshold trespassed.",
|
||||||
|
"iAMT0013": "Intel(R) AMT Network Interface %1s heuristics defense Encounter timeout expired.",
|
||||||
|
"iAMT0014": "General certificate error.",
|
||||||
|
"iAMT0015": "Certificate expired.",
|
||||||
|
"iAMT0016": "No trusted root certificate.",
|
||||||
|
"iAMT0017": "Not configured to work with server certificate.",
|
||||||
|
"iAMT0018": "Certificate revoked.",
|
||||||
|
"iAMT0019": "RSA exponent too large.",
|
||||||
|
"iAMT0020": "RSA modulus too large.",
|
||||||
|
"iAMT0021": "Unsupported digest.",
|
||||||
|
"iAMT0022": "Distinguished name too long.",
|
||||||
|
"iAMT0023": "Key usage missing.",
|
||||||
|
"iAMT0024": "General SSL handshake error.",
|
||||||
|
"iAMT0025": "General 802.1x error.",
|
||||||
|
"iAMT0026": "AMT Diagnostic AlertEAC error - General NAC error.",
|
||||||
|
"iAMT0027": "AMT Diagnostic AlertEAC error - attempt to get a NAC posture while AMT NAC is disabled.",
|
||||||
|
"iAMT0028": "AMT Diagnostic AlertEAC error - attempt to get a posture of an unsupported type.",
|
||||||
|
"iAMT0029": "Audit log storage is 50% full.",
|
||||||
|
"iAMT0030": "Audit log storage is 75% full.",
|
||||||
|
"iAMT0031": "Audit log storage is 85% full.",
|
||||||
|
"iAMT0032": "Audit log storage is 95% full.",
|
||||||
|
"iAMT0033": "Audit log storage is full.",
|
||||||
|
"iAMT0034": "Firmware Update Event - Partial.",
|
||||||
|
"iAMT0035": "Firmware Update Event - Failure.",
|
||||||
|
"iAMT0036": "Remote connectivity initiated.",
|
||||||
|
"iAMT0037": "ME Presence event.",
|
||||||
|
"iAMT0038-0": "AMT is being unprovisioned using BIOS command.",
|
||||||
|
"iAMT0038-1": "AMT is being unprovisioned using Local MEI command.",
|
||||||
|
"iAMT0038-2": "AMT is being unprovisioned using Local WS-MAN/SOAP command.",
|
||||||
|
"iAMT0038-3": "AMT is being unprovisioned using Remote WS-MAN/SOAP command.",
|
||||||
|
"iAMT0039": "HW Asset Error.",
|
||||||
|
"iAMT0050": "User Notification Alert - General Notification.",
|
||||||
|
"iAMT0050-16": "User Notification Alert - Circuit Breaker notification (CB Drop TX filter hit.).",
|
||||||
|
"iAMT0050-17": "User Notification Alert - Circuit Breaker notification (CB Rate Limit TX filter hit.).",
|
||||||
|
"iAMT0050-18": "User Notification Alert - Circuit Breaker notification (CB Drop RX filter hit.).",
|
||||||
|
"iAMT0050-19": "User Notification Alert - Circuit Breaker notification (CB Rate Limit RX filter hit.).",
|
||||||
|
"iAMT0050-32": "User Notification Alert - EAC notification.",
|
||||||
|
"iAMT0050-48": "User Notification Alert - Remote diagnostics - (Remote Redirection session started - SOL).",
|
||||||
|
"iAMT0050-49": "User Notification Alert - Remote diagnostics - (Remote Redirection session stopped - SOL).",
|
||||||
|
"iAMT0050-50": "User Notification Alert - Remote diagnostics. (Remote Redirection session started - IDE-R).",
|
||||||
|
"iAMT0050-51": "User Notification Alert - Remote diagnostics. (Remote Redirection session stopped - IDE-R).",
|
||||||
|
"iAMT0050-66": "User Notification Alert - WLAN notification (Host profile mismatch - Management Interface ignored).",
|
||||||
|
"iAMT0050-67": "User Notification Alert - WLAN notification (Management device overrides host radio).",
|
||||||
|
"iAMT0050-68": "User Notification Alert - WLAN notification (Host profile security mismatch).",
|
||||||
|
"iAMT0050-69": "User Notification Alert - WLAN notification (Management device relinquishes control over host Radio).",
|
||||||
|
"iAMT0051": "User Notification Alert - SecIo event.",
|
||||||
|
"iAMT0051-0": "User Notification Alert - SecIo event semaphore at host.",
|
||||||
|
"iAMT0051-1": "User Notification Alert - semaphore at ME.",
|
||||||
|
"iAMT0051-2": "User Notification Alert - SecIo event - semaphore timeout.",
|
||||||
|
"iAMT0052": "User Notification Alert - KVM session event.",
|
||||||
|
"iAMT0052-0": "User Notification Alert - KVM session requested.",
|
||||||
|
"iAMT0052-1": "User Notification Alert - KVM session started.",
|
||||||
|
"iAMT0052-2": "User Notification Alert - KVM session stopped.",
|
||||||
|
"iAMT0052-3": "User Notification Alert - KVM data channel.",
|
||||||
|
"iAMT0053": "User Notification Alert - RCS notification.",
|
||||||
|
"iAMT0053-50": "User Notification Alert - RCS notification (HW button pressed. Connection initiated automatically).",
|
||||||
|
"iAMT0053-52": "User Notification Alert - RCS notification (HW button pressed. Connection wasn't initiated automatically).",
|
||||||
|
"iAMT0053-53": "User Notification Alert - RCS notification (Contracts updated).",
|
||||||
|
"iAMT0054": "User Notification Alert - WLAN notification. Wireless Profile sync enablement state changed.",
|
||||||
|
"iAMT0055": "User Notification Alert - Provisioning state change notification.",
|
||||||
|
"iAMT0055-0": "User Notification Alert - Provisioning state change notification - Pre-configuration.",
|
||||||
|
"iAMT0055-1": "User Notification Alert - Provisioning state change notification - In configuration.",
|
||||||
|
"iAMT0055-2": "User Notification Alert - Provisioning state change notification - Post-configuration.",
|
||||||
|
"iAMT0055-3": "User Notification Alert - Provisioning state change notification - Unprovision process has started.",
|
||||||
|
"iAMT0056": "User Notification Alert - System Defense change notification.",
|
||||||
|
"iAMT0057": "User Notification Alert - Network State change notification.",
|
||||||
|
"iAMT0058": "User Notification Alert - Remote Access change notification.",
|
||||||
|
"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is closed.",
|
||||||
|
//"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is open.", // TODO
|
||||||
|
"iAMT0059": "User Notification Alert - KVM enabled event.",
|
||||||
|
"iAMT0059-0": "User Notification Alert - KVM enabled event - KVM disabled.",
|
||||||
|
"iAMT0059-1": "User Notification Alert - KVM enabled event - KVM enabled (both from MEBx and PTNI).",
|
||||||
|
"iAMT0060": "User Notification Alert - SecIO configuration event.",
|
||||||
|
"iAMT0061": "ME FW reset occurred.",
|
||||||
|
"iAMT0062": "User Notification Alert - IpSyncEnabled event.",
|
||||||
|
"iAMT0062-0": "User Notification Alert - IpSyncEnabled event - IpSync disabled.",
|
||||||
|
"iAMT0062-1": "User Notification Alert - IpSyncEnabled event - IpSync enabled.",
|
||||||
|
"iAMT0063": "User Notification Alert - HTTP Proxy sync enabled event.",
|
||||||
|
"iAMT0063-0": "User Notification Alert - HTTP Proxy sync enabled event - HTTP Proxy Sync disabled.",
|
||||||
|
"iAMT0063-1": "User Notification Alert - HTTP Proxy sync enabled event - HTTP Proxy Sync enabled.",
|
||||||
|
"iAMT0064": "User Notification Alert - User Consent event.",
|
||||||
|
"iAMT0064-1": "User Notification Alert - User Consent event - User Consent granted.",
|
||||||
|
"iAMT0064-2": "User Notification Alert - User Consent event - User Consent ended.",
|
||||||
|
"iAMT0067-0": "Graceful Remote Control Operation - Shutdown.",
|
||||||
|
"iAMT0067-1": "Graceful Remote Control Operation - Reset.",
|
||||||
|
"iAMT0067-2": "Graceful Remote Control Operation - Hibernate.",
|
||||||
|
"iAMT0068-0": "Link Protection Notification - No link protection.",
|
||||||
|
"iAMT0068-1": "Link Protection Notification - Passive link protection.",
|
||||||
|
"iAMT0068-2": "Link Protection Notification - High link protection.",
|
||||||
|
"iAMT0069-0": "Local Time Sync Enablement Notification - Local Time Sync Disabled.",
|
||||||
|
"iAMT0069-1": "Local Time Sync Enablement Notification - Local Time Sync Enabled.",
|
||||||
|
"iAMT0070": "Host Reset Triggered by WD Expiration Notification.",
|
||||||
|
"PLAT0004": "The chassis %1s was opened.",
|
||||||
|
"PLAT0005": "The chassis %1s was closed.",
|
||||||
|
"PLAT0006": "The drive bay %1s was opened.",
|
||||||
|
"PLAT0007": "The drive bay %1s was closed.",
|
||||||
|
"PLAT0008": "The I/O card area %1s was opened.",
|
||||||
|
"PLAT0009": "The I/O card area %1s was closed.",
|
||||||
|
"PLAT0010": "The processor area %1s was opened.",
|
||||||
|
"PLAT0011": "The processor area %1s was closed.",
|
||||||
|
"PLAT0012": "The LAN %1s has been disconnected.",
|
||||||
|
"PLAT0013": "The LAN %1s has been connected.",
|
||||||
|
"PLAT0016": "The permission to insert package %1s has been granted.",
|
||||||
|
"PLAT0017": "The permission to insert package %1s has been removed.",
|
||||||
|
"PLAT0018": "The fan card area %1s is open.",
|
||||||
|
"PLAT0019": "The fan card area %1s is closed.",
|
||||||
|
"PLAT0022": "The computer system %1s has detected a secure mode violation.",
|
||||||
|
"PLAT0024": "The computer system %1s has detected a pre-boot user password violation.",
|
||||||
|
"PLAT0026": "The computer system %1s has detected a pre-boot setup password violation.",
|
||||||
|
"PLAT0028": "The computer system %1s has detected a network boot password violation.",
|
||||||
|
"PLAT0030": "The computer system %1s has detected a password violation.",
|
||||||
|
"PLAT0032": "The management controller %1s has detected an out-of-band password violation.",
|
||||||
|
"PLAT0034": "The processor %1s has been added.",
|
||||||
|
"PLAT0035": "The processor %1s has been removed.",
|
||||||
|
"PLAT0036": "An over-temperature condition has been detected on the processor %1s.",
|
||||||
|
"PLAT0037": "An over-temperature condition has been removed on the processor %1s.",
|
||||||
|
"PLAT0038": "The processor %1s is operating in a degraded State.",
|
||||||
|
"PLAT0039": "The processor %1s is no longer operating in a degraded State.",
|
||||||
|
"PLAT0040": "The processor %1s has failed.",
|
||||||
|
"PLAT0042": "The processor %1s has failed.",
|
||||||
|
"PLAT0044": "The processor %1s has failed.",
|
||||||
|
"PLAT0046": "The processor %1s has failed.",
|
||||||
|
"PLAT0048": "The processor %1s has failed.",
|
||||||
|
"PLAT0060": "The processor %1s has been enabled.",
|
||||||
|
"PLAT0061": "The processor %1s has been disabled.",
|
||||||
|
"PLAT0062": "The processor %1s has a configuration mismatch.",
|
||||||
|
"PLAT0064": "A terminator has been detected on the processor %1s.",
|
||||||
|
"PLAT0084": "The Power Supply %1s has been added.",
|
||||||
|
"PLAT0085": "The Power Supply %1s has been removed.",
|
||||||
|
"PLAT0086": "The Power Supply %1s has failed.",
|
||||||
|
"PLAT0088": "Failure predicted on power supply %1s.",
|
||||||
|
"PLAT0096": "The input to power supply %1s has been lost or fallen out of range.",
|
||||||
|
"PLAT0098": "The power supply %1s is operating in an input state that is out of range.",
|
||||||
|
"PLAT0099": "The power supply %1s has returned to a normal input state.",
|
||||||
|
"PLAT0100": "The power supply %1s has lost input.",
|
||||||
|
"PLAT0104": "The power supply %1s has a configuration mismatch.",
|
||||||
|
"PLAT0106": "Power supply %1s has been disabled.",
|
||||||
|
"PLAT0107": "Power supply %1s has been enabled.",
|
||||||
|
"PLAT0108": "Power supply %1s has been power cycled.",
|
||||||
|
"PLAT0110": "Power supply %1s has encountered an error during power down.",
|
||||||
|
"PLAT0112": "Power supply %1s has lost power.",
|
||||||
|
"PLAT0114": "Soft power control has failed for power supply %1s.",
|
||||||
|
"PLAT0116": "Power supply %1s has failed.",
|
||||||
|
"PLAT0118": "Failure predicted on power supply %1s.",
|
||||||
|
"PLAT0120": "Memory subsystem failure.",
|
||||||
|
"PLAT0122": "DIMM missing.",
|
||||||
|
"PLAT0124": "Memory error detected & corrected for DIMM %1s.",
|
||||||
|
"PLAT0128": "Memory DIMM %1s added.",
|
||||||
|
"PLAT0129": "Memory DIMM %1s removed.",
|
||||||
|
"PLAT0130": "Memory DIMM %1s enabled.",
|
||||||
|
"PLAT0131": "Memory DIMM %1s disabled.",
|
||||||
|
"PLAT0134": "Memory parity error for DIMM %1s.",
|
||||||
|
"PLAT0136": "Memory scrub failure for DIMM %1s.",
|
||||||
|
"PLAT0138": "Memory uncorrectable error detected for DIMM %1s.",
|
||||||
|
"PLAT0140": "Memory sparing initiated for DIMM %1s.",
|
||||||
|
"PLAT0141": "Memory sparing concluded for DIMM %1s.",
|
||||||
|
"PLAT0142": "Memory DIMM %1s Throttled.",
|
||||||
|
"PLAT0144": "Memory logging limit reached for DIMM %1s.",
|
||||||
|
"PLAT0145": "Memory logging limit removed for DIMM %1s.",
|
||||||
|
"PLAT0146": "An over-temperature condition has been detected on the Memory DIMM %1s.",
|
||||||
|
"PLAT0147": "An over-temperature condition has been removed on the Memory DIMM %1s.",
|
||||||
|
"PLAT0162": "The drive %1s has been added.",
|
||||||
|
"PLAT0163": "The drive %1s has been removed.",
|
||||||
|
"PLAT0164": "The drive %1s has been disabled due to a detected fault.",
|
||||||
|
"PLAT0167": "The drive %1s has been enabled.",
|
||||||
|
"PLAT0168": "Failure predicted on drive %1s.",
|
||||||
|
"PLAT0170": "Hot spare enabled for %1s.",
|
||||||
|
"PLAT0171": "Hot spare disabled for %1s.",
|
||||||
|
"PLAT0172": "Consistency check has begun for %1s.",
|
||||||
|
"PLAT0173": "Consistency check completed for %1s.",
|
||||||
|
"PLAT0174": "Array %1s is in critical condition.",
|
||||||
|
"PLAT0176": "Array %1s has failed.",
|
||||||
|
"PLAT0177": "Array %1s has been restored.",
|
||||||
|
"PLAT0178": "Rebuild in progress for array %1s.",
|
||||||
|
"PLAT0179": "Rebuild completed for array %1s.",
|
||||||
|
"PLAT0180": "Rebuild Aborted for array %1s.",
|
||||||
|
"PLAT0184": "The system %1s encountered a POST error.",
|
||||||
|
"PLAT0186": "The system %1s encountered a firmware hang.",
|
||||||
|
"PLAT0188": "The system %1s encountered firmware progress.",
|
||||||
|
"PLAT0192": "The log %1s has been disabled.",
|
||||||
|
"PLAT0193": "The log %1s has been enabled.",
|
||||||
|
"PLAT0194": "The log %1s has been disabled.",
|
||||||
|
"PLAT0195": "The log %1s has been enabled.",
|
||||||
|
"PLAT0196": "The log %1s has been disabled.",
|
||||||
|
"PLAT0198": "The log %1s has been enabled.",
|
||||||
|
"PLAT0200": "The log %1s has been cleared.",
|
||||||
|
"PLAT0202": "The log %1s is full.",
|
||||||
|
"PLAT0203": "The log %1s is no longer full.",
|
||||||
|
"PLAT0204": "The log %1s is almost full.",
|
||||||
|
"PLAT0208": "The log %1s has a configuration error.",
|
||||||
|
"PLAT0210": "The system %1s has been reconfigured.",
|
||||||
|
"PLAT0212": "The system %1s has encountered an OEM system boot event.",
|
||||||
|
"PLAT0214": "The system %1s has encountered an unknown system hardware fault.",
|
||||||
|
"PLAT0216": "The system %1s has generated an auxiliary log entry.",
|
||||||
|
"PLAT0218": "The system %1s has executed a PEF action.",
|
||||||
|
"PLAT0220": "The system %1s has synchronized the system clock.",
|
||||||
|
"PLAT0222": "A diagnostic interrupt has occurred on system %1s.",
|
||||||
|
"PLAT0224": "A bus timeout has occurred on system %1s.",
|
||||||
|
"PLAT0226": "An I/O channel check NMI has occurred on system %1s.",
|
||||||
|
"PLAT0228": "A software NMI has occurred on system %1s.",
|
||||||
|
"PLAT0230": "System %1s has recovered from an NMI.",
|
||||||
|
"PLAT0232": "A PCI PERR has occurred on system %1s.",
|
||||||
|
"PLAT0234": "A PCI SERR has occurred on system %1s.",
|
||||||
|
"PLAT0236": "An EISA fail safe timeout occurred on system %1s.",
|
||||||
|
"PLAT0238": "A correctable bus error has occurred on system %1s.",
|
||||||
|
"PLAT0240": "An uncorrectable bus error has occurred on system %1s.",
|
||||||
|
"PLAT0242": "A fatal NMI error has occurred on system %1s.",
|
||||||
|
"PLAT0244": "A fatal bus error has occurred on system %1s.",
|
||||||
|
"PLAT0246": "A bus on system %1s is operating in a degraded state.",
|
||||||
|
"PLAT0247": "A bus on system %1s is no longer operating in a degraded state.",
|
||||||
|
"PLAT0248": "The power button %1s has been pressed.",
|
||||||
|
"PLAT0249": "The power button %1s has been released.",
|
||||||
|
"PLAT0250": "The sleep button %1s has been pressed.",
|
||||||
|
"PLAT0251": "The sleep button %1s has been released.",
|
||||||
|
"PLAT0252": "The reset button %1s has been pressed.",
|
||||||
|
"PLAT0253": "The reset button %1s has been released.",
|
||||||
|
"PLAT0254": "The latch to %1s has been opened.",
|
||||||
|
"PLAT0255": "The latch to %1s has been closed.",
|
||||||
|
"PLAT0256": "The service request %1s has been enabled.",
|
||||||
|
"PLAT0257": "The service request %1s has been completed.",
|
||||||
|
"PLAT0258": "Power control of system %1s has failed.",
|
||||||
|
"PLAT0262": "The network port %1s has been connected.",
|
||||||
|
"PLAT0263": "The network port %1s has been disconnected.",
|
||||||
|
"PLAT0266": "The connector %1s has encountered a configuration error.",
|
||||||
|
"PLAT0267": "The connector %1s configuration error has been repaired.",
|
||||||
|
"PLAT0272": "Power on for system %1s.",
|
||||||
|
"PLAT0274": "Power cycle hard requested for system %1s.",
|
||||||
|
"PLAT0276": "Power cycle soft requested for system %1s.",
|
||||||
|
"PLAT0278": "PXE boot requested for system %1s.",
|
||||||
|
"PLAT0280": "Diagnostics boot requested for system %1s.",
|
||||||
|
"PLAT0282": "System restart requested for system %1s.",
|
||||||
|
"PLAT0284": "System restart begun for system %1s.",
|
||||||
|
"PLAT0286": "No bootable media available for system %1s.",
|
||||||
|
"PLAT0288": "Non-bootable media selected for system %1s.",
|
||||||
|
"PLAT0290": "PXE server not found for system %1s.",
|
||||||
|
"PLAT0292": "User timeout on boot for system %1s.",
|
||||||
|
"PLAT0296": "System %1s boot from floppy initiated.",
|
||||||
|
"PLAT0298": "System %1s boot from local drive initiated.",
|
||||||
|
"PLAT0300": "System %1s boot from PXE on network port initiated.",
|
||||||
|
"PLAT0302": "System %1s boot diagnostics initiated.",
|
||||||
|
"PLAT0304": "System %1s boot from CD initiated.",
|
||||||
|
"PLAT0306": "System %1s boot from ROM initiated.",
|
||||||
|
"PLAT0312": "System %1s boot initiated.",
|
||||||
|
"PLAT0320": "Critical stop during OS load on system %1s.",
|
||||||
|
"PLAT0322": "Run-time critical stop on system %1s.",
|
||||||
|
"PLAT0324": "OS graceful stop on system %1s.",
|
||||||
|
"PLAT0326": "OS graceful shutdown begun on system %1s.",
|
||||||
|
"PLAT0327": "OS graceful shutdown completed on system %1s.",
|
||||||
|
"PLAT0328": "Agent not responding on system %1s.",
|
||||||
|
"PLAT0329": "Agent has begun responding on system %1s.",
|
||||||
|
"PLAT0330": "Fault in slot on system %1s.",
|
||||||
|
"PLAT0331": "Fault condition removed on system %1s.",
|
||||||
|
"PLAT0332": "Identifying slot on system %1s.",
|
||||||
|
"PLAT0333": "Identify stopped on slot for system %1s.",
|
||||||
|
"PLAT0334": "Package installed in slot for system %1s.",
|
||||||
|
"PLAT0336": "Slot empty system %1s.",
|
||||||
|
"PLAT0338": "Slot in system %1s is ready for installation.",
|
||||||
|
"PLAT0340": "Slot in system %1s is ready for removal.",
|
||||||
|
"PLAT0342": "Power is off on slot of system %1s.",
|
||||||
|
"PLAT0344": "Power is on for slot of system %1s.",
|
||||||
|
"PLAT0346": "Removal requested for slot of system %1s.",
|
||||||
|
"PLAT0348": "Interlock activated on slot of system %1s.",
|
||||||
|
"PLAT0349": "Interlock de-asserted on slot of system %1s.",
|
||||||
|
"PLAT0350": "Slot disabled on system %1s.",
|
||||||
|
"PLAT0351": "Slot enabled on system %1s.",
|
||||||
|
"PLAT0352": "Slot of system %1s holds spare.",
|
||||||
|
"PLAT0353": "Slot of system %1s no longer holds spare.",
|
||||||
|
"PLAT0354": "Computer system %1s enabled.",
|
||||||
|
"PLAT0356": "Computer system %1s is in sleep - light mode.",
|
||||||
|
"PLAT0358": "Computer system %1s is in hibernate.",
|
||||||
|
"PLAT0360": "Computer system %1s is in standby.",
|
||||||
|
"PLAT0362": "Computer system %1s is in soft off mode.",
|
||||||
|
"PLAT0364": "Computer system %1s is in hard off mode.",
|
||||||
|
"PLAT0366": "Computer system %1s is sleeping.",
|
||||||
|
"PLAT0368": "Watchdog timer expired for %1s.",
|
||||||
|
"PLAT0370": "Reboot of system initiated by watchdog %1s.",
|
||||||
|
"PLAT0372": "Powering off system initiated by watchdog %1s.",
|
||||||
|
"PLAT0374": "Power cycle of system initiated by watchdog %1s.",
|
||||||
|
"PLAT0376": "Watchdog timer interrupt occurred for %1s.",
|
||||||
|
"PLAT0378": "A page alert has been generated for system %1s.",
|
||||||
|
"PLAT0380": "A LAN alert has been generated for system %1s.",
|
||||||
|
"PLAT0382": "An event trap has been generated for system %1s.",
|
||||||
|
"PLAT0384": "An SNMP trap has been generated for system %1s.",
|
||||||
|
"PLAT0390": "%1s detected as present.",
|
||||||
|
"PLAT0392": "%1s detected as absent.",
|
||||||
|
"PLAT0394": "%1s has been disabled.",
|
||||||
|
"PLAT0395": "%1s has been enabled.",
|
||||||
|
"PLAT0396": "Heartbeat lost for LAN %1s.",
|
||||||
|
"PLAT0397": "Heartbeat detected for LAN %1s.",
|
||||||
|
"PLAT0398": "Sensor %1s is unavailable or degraded on management system.",
|
||||||
|
"PLAT0399": "Sensor %1s has returned to normal on management system.",
|
||||||
|
"PLAT0400": "Controller %1s is unavailable or degraded on management system.",
|
||||||
|
"PLAT0401": "Controller %1s has returned to normal on management system.",
|
||||||
|
"PLAT0402": "Management system %1s is off-line.",
|
||||||
|
"PLAT0404": "Management system %1s is disabled.",
|
||||||
|
"PLAT0405": "Management system %1s is enabled.",
|
||||||
|
"PLAT0406": "Sensor %1s has failed on management system.",
|
||||||
|
"PLAT0408": "FRU %1s has failed on management system.",
|
||||||
|
"PLAT0424": "The battery %1s is critically low.",
|
||||||
|
"PLAT0427": "The battery %1s is no longer critically low.",
|
||||||
|
"PLAT0430": "The battery %1s has been removed from unit.",
|
||||||
|
"PLAT0431": "The battery %1s has been added.",
|
||||||
|
"PLAT0432": "The battery %1s has failed.",
|
||||||
|
"PLAT0434": "Session audit is deactivated on system %1s.",
|
||||||
|
"PLAT0435": "Session audit is activated on system %1s.",
|
||||||
|
"PLAT0436": "A hardware change occurred on system %1s.",
|
||||||
|
"PLAT0438": "A firmware or software change occurred on system %1s.",
|
||||||
|
"PLAT0440": "A hardware incompatibility was detected on system %1s.",
|
||||||
|
"PLAT0442": "A firmware or software incompatibility was detected on system %1s.",
|
||||||
|
"PLAT0444": "Invalid or unsupported hardware was detected on system %1s.",
|
||||||
|
"PLAT0446": "Invalid or unsupported firmware or software was detected on system %1s.",
|
||||||
|
"PLAT0448": "A successful hardware change was detected on system %1s.",
|
||||||
|
"PLAT0450": "A successful software or firmware change was detected on system %1s.",
|
||||||
|
"PLAT0464": "FRU %1s not installed on system.",
|
||||||
|
"PLAT0465": "FRU %1s installed on system.",
|
||||||
|
"PLAT0466": "Activation requested for FRU %1s on system.",
|
||||||
|
"PLAT0467": "FRU %1s on system is active.",
|
||||||
|
"PLAT0468": "Activation in progress for FRU %1s on system.",
|
||||||
|
"PLAT0470": "Deactivation request for FRU %1s on system.",
|
||||||
|
"PLAT0471": "FRU %1s on system is in standby or \"hot spare\" state.",
|
||||||
|
"PLAT0472": "Deactivation in progress for FRU %1s on system.",
|
||||||
|
"PLAT0474": "Communication lost with FRU %1s on system.",
|
||||||
|
"PLAT0476": "Numeric sensor %1s going low (lower non-critical).",
|
||||||
|
"PLAT0478": "Numeric sensor %1s going high (lower non-critical).",
|
||||||
|
"PLAT0480": "Numeric sensor %1s going low (lower critical).",
|
||||||
|
"PLAT0482": "Numeric sensor %1s going high (lower critical).",
|
||||||
|
"PLAT0484": "Numeric sensor %1s going low (lower non-recoverable).",
|
||||||
|
"PLAT0486": "Numeric sensor %1s going high (lower non-critical).",
|
||||||
|
"PLAT0488": "Numeric sensor %1s going low (upper non-critical).",
|
||||||
|
"PLAT0490": "Numeric sensor %1s going high (upper non-critical).",
|
||||||
|
"PLAT0492": "Numeric sensor %1s going low (upper critical).",
|
||||||
|
"PLAT0494": "Numeric sensor %1s going high (upper critical).",
|
||||||
|
"PLAT0496": "Numeric sensor %1s going low (upper non-recoverable).",
|
||||||
|
"PLAT0498": "Numeric sensor %1s going high (upper non-recoverable).",
|
||||||
|
"PLAT0500": "Sensor %1s has transitioned to idle.",
|
||||||
|
"PLAT0502": "Sensor %1s has transitioned to active.",
|
||||||
|
"PLAT0504": "Sensor %1s has transitioned to busy.",
|
||||||
|
"PLAT0508": "Sensor %1s has asserted.",
|
||||||
|
"PLAT0509": "Sensor %1s has de-asserted.",
|
||||||
|
"PLAT0510": "Sensor %1s is asserting predictive failure.",
|
||||||
|
"PLAT0511": "Sensor %1s is de-asserting predictive failure.",
|
||||||
|
"PLAT0512": "Sensor %1s has indicated limit exceeded.",
|
||||||
|
"PLAT0513": "Sensor %1s has indicated limit no longer exceeded.",
|
||||||
|
"PLAT0514": "Sensor %1s has indicated performance met.",
|
||||||
|
"PLAT0516": "Sensor %1s has indicated performance lags.",
|
||||||
|
"PLAT0518": "Sensor %1s has transitioned to normal state.",
|
||||||
|
"PLAT0520": "Sensor %1s has transitioned from normal to non-critical state.",
|
||||||
|
"PLAT0522": "Sensor %1s has transitioned to critical from a less severe state.",
|
||||||
|
"PLAT0524": "Sensor %1s has transitioned to non-recoverable from a less severe state.",
|
||||||
|
"PLAT0526": "Sensor %1s has transitioned to non-critical from a more severe state.",
|
||||||
|
"PLAT0528": "Sensor %1s has transitioned to critical from a non-recoverable state.",
|
||||||
|
"PLAT0530": "Sensor %1s has transitioned to non-recoverable.",
|
||||||
|
"PLAT0532": "Sensor %1s indicates a monitor state.",
|
||||||
|
"PLAT0534": "Sensor %1s has an informational state.",
|
||||||
|
"PLAT0536": "Device %1s has been added.",
|
||||||
|
"PLAT0537": "Device %1s has been removed from unit.",
|
||||||
|
"PLAT0538": "Device %1s has been enabled.",
|
||||||
|
"PLAT0539": "Device %1s has been disabled.",
|
||||||
|
"PLAT0540": "Sensor %1s has indicated a running state.",
|
||||||
|
"PLAT0544": "Sensor %1s has indicated a power off state.",
|
||||||
|
"PLAT0546": "Sensor %1s has indicated an on-line state.",
|
||||||
|
"PLAT0548": "Sensor %1s has indicated an off-line state.",
|
||||||
|
"PLAT0550": "Sensor %1s has indicated an off-duty state.",
|
||||||
|
"PLAT0552": "Sensor %1s has indicated a degraded state.",
|
||||||
|
"PLAT0554": "Sensor %1s has indicated a power save state.",
|
||||||
|
"PLAT0556": "Sensor %1s has indicated an install error.",
|
||||||
|
"PLAT0558": "Redundancy %1s has been lost.",
|
||||||
|
"PLAT0560": "Redundancy %1s has been reduced.",
|
||||||
|
"PLAT0561": "Redundancy %1s has been restored.",
|
||||||
|
"PLAT0562": "%1s has transitioned to a D0 power state.",
|
||||||
|
"PLAT0564": "%1s has transitioned to a D1 power state.",
|
||||||
|
"PLAT0566": "%1s has transitioned to a D2 power state.",
|
||||||
|
"PLAT0568": "%1s has transitioned to a D3 power state.",
|
||||||
|
"PLAT0720": "The System %1s encountered firmware progress - memory initialization entry.",
|
||||||
|
"PLAT0721": "The System %1s encountered firmware progress - memory initialization exit.",
|
||||||
|
"PLAT0722": "The System %1s encountered firmware progress - hard drive initialization entry.",
|
||||||
|
"PLAT0723": "The System %1s encountered firmware progress - hard drive initialization exit.",
|
||||||
|
"PLAT0724": "The System %1s encountered firmware progress - user authentication.",
|
||||||
|
"PLAT0728": "The System %1s encountered firmware progress - USR resource configuration entry.",
|
||||||
|
"PLAT0729": "The System %1s encountered firmware progress - USR resource configuration exit.",
|
||||||
|
"PLAT0730": "The System %1s encountered firmware progress - PCI recource configuration entry.",
|
||||||
|
"PLAT0731": "The System %1s encountered firmware progress - PCI recource configuration exit.",
|
||||||
|
"PLAT0732": "The System %1s encountered firmware progress - Option ROM initialization entry.",
|
||||||
|
"PLAT0733": "The System %1s encountered firmware progress - Option ROM initialization entry exit.",
|
||||||
|
"PLAT0734": "The System %1s encountered firmware progress -video initialization entry entry.",
|
||||||
|
"PLAT0735": "The System %1s encountered firmware progress - video initialization entry exit.",
|
||||||
|
"PLAT0736": "The System %1s encountered firmware progress - cache initialization entry.",
|
||||||
|
"PLAT0737": "The System %1s encountered firmware progress - cache initialization exit.",
|
||||||
|
"PLAT0738": "The System %1s encountered firmware progress - keyboard controller initialization entry.",
|
||||||
|
"PLAT0739": "The System %1s encountered firmware progress - keyboard controller initialization exit.",
|
||||||
|
"PLAT0740": "The System %1s encountered firmware progress - motherboard initialization entry.",
|
||||||
|
"PLAT0741": "The System %1s encountered firmware progress - motherboard initialization exit.",
|
||||||
|
"PLAT0742": "The System %1s encountered firmware progress - floppy disk initialization entry.",
|
||||||
|
"PLAT0743": "The System %1s encountered firmware progress - floppy disk initialization exit.",
|
||||||
|
"PLAT0744": "The System %1s encountered firmware progress - keyboard test entry.",
|
||||||
|
"PLAT0745": "The System %1s encountered firmware progress - keyboard test exit.",
|
||||||
|
"PLAT0746": "The System %1s encountered firmware progress - pointing device test entry.",
|
||||||
|
"PLAT0747": "The System %1s encountered firmware progress - pointing device test exit.",
|
||||||
|
"PLAT0750": "The System %1s encountered firmware progress - dock enable entry.",
|
||||||
|
"PLAT0751": "The System %1s encountered firmware progress - dock enable exit.",
|
||||||
|
"PLAT0752": "The System %1s encountered firmware progress - dock disable entry.",
|
||||||
|
"PLAT0753": "The System %1s encountered firmware progress - dock disable exit.",
|
||||||
|
"PLAT0760": "The System %1s encountered firmware progress - start OS boot process.",
|
||||||
|
"PLAT0762": "The System %1s encountered firmware progress - call OS wake vector.",
|
||||||
|
"PLAT0764": "The System %1s encountered firmware progress - unrecoverable keyboard failure.",
|
||||||
|
"PLAT0766": "The System %1s encountered firmware progress - no video device detected.",
|
||||||
|
"PLAT0768": "The System %1s encountered firmware progress - SMART alert detected on drive.",
|
||||||
|
"PLAT0770": "The System %1s encountered firmware progress - unrecoverable boot device failure.",
|
||||||
|
"PLAT0789": "Corrupt BIOS detected.",
|
||||||
|
"PLAT0790": "The System %1s encountered PCI configuration failure.",
|
||||||
|
"PLAT0791": "The System %1s encountered a video subsystem failure.",
|
||||||
|
"PLAT0792": "The System %1s encountered a storage subsystem failure.",
|
||||||
|
"PLAT0793": "The System %1s encountered a USB subsystem failure.",
|
||||||
|
"PLAT0794": "The System %1s has detected no memory in the system.",
|
||||||
|
"PLAT0795": "The System %1s encountered a motherboard failure.",
|
||||||
|
"PLAT0796": "The System %1s encountered a memory Regulator Voltage Bad.",
|
||||||
|
"PLAT0797": "%1s PCI reset is not deasserting.",
|
||||||
|
"PLAT0798": "%1s Non-Motherboard Regulator Failure.",
|
||||||
|
"PLAT0799": "%1s Power Supply Cable failure.",
|
||||||
|
"PLAT0800": "%1s Motherboard regulator failure.",
|
||||||
|
"PLAT0801": "%1s System component compatibility mismatch."
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = lme_heci;
|
417
agents-new/modules_meshcmd/amt-mei.js
Normal file
417
agents-new/modules_meshcmd/amt-mei.js
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Q = require('queue');
|
||||||
|
function amt_heci() {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
|
||||||
|
var heci = require('heci');
|
||||||
|
|
||||||
|
this._ObjectID = "pthi";
|
||||||
|
this._rq = new Q();
|
||||||
|
this._setupPTHI = function _setupPTHI()
|
||||||
|
{
|
||||||
|
this._amt = heci.create();
|
||||||
|
this._amt.BiosVersionLen = 65;
|
||||||
|
this._amt.UnicodeStringLen = 20;
|
||||||
|
|
||||||
|
this._amt.Parent = this;
|
||||||
|
this._amt.on('error', function _amtOnError(e)
|
||||||
|
{
|
||||||
|
if(this.Parent._rq.isEmpty())
|
||||||
|
{
|
||||||
|
this.Parent.emit('error', e); // No pending requests, so propagate the error up
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There is a pending request, so fail the pending request
|
||||||
|
var user = this.Parent._rq.deQueue();
|
||||||
|
var params = user.optional;
|
||||||
|
var callback = user.func;
|
||||||
|
params.unshift({ Status: -1 }); // Relay an error
|
||||||
|
callback.apply(this.Parent, params);
|
||||||
|
|
||||||
|
if(!this.Parent._rq.isEmpty())
|
||||||
|
{
|
||||||
|
// There are still more pending requests, so try to re-helpconnect MEI
|
||||||
|
this.connect(heci.GUIDS.AMT, { noPipeline: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._amt.on('connect', function _amtOnConnect()
|
||||||
|
{
|
||||||
|
this.on('data', function _amtOnData(chunk)
|
||||||
|
{
|
||||||
|
//console.log("Received: " + chunk.length + " bytes");
|
||||||
|
var header = this.Parent.getCommand(chunk);
|
||||||
|
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
|
||||||
|
|
||||||
|
var user = this.Parent._rq.deQueue();
|
||||||
|
var params = user.optional;
|
||||||
|
var callback = user.func;
|
||||||
|
|
||||||
|
params.unshift(header);
|
||||||
|
callback.apply(this.Parent, params);
|
||||||
|
|
||||||
|
if(this.Parent._rq.isEmpty())
|
||||||
|
{
|
||||||
|
// No More Requests, we can close PTHI
|
||||||
|
this.Parent._amt.disconnect();
|
||||||
|
this.Parent._amt = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send the next request
|
||||||
|
this.write(this.Parent._rq.peekQueue().send);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start sending requests
|
||||||
|
this.write(this.Parent._rq.peekQueue().send);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function trim(x) { var y = x.indexOf('\0'); if (y >= 0) { return x.substring(0, y); } else { return x; } }
|
||||||
|
this.getCommand = function getCommand(chunk) {
|
||||||
|
var command = chunk.length == 0 ? (this._rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
|
||||||
|
var ret = { IsResponse: (command & 0x800000) == 0x800000 ? true : false, Command: (command & 0x7FFFFF), Status: chunk.length != 0 ? chunk.readUInt32LE(12) : -1, Data: chunk.length != 0 ? chunk.slice(16) : null };
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sendCommand = function sendCommand()
|
||||||
|
{
|
||||||
|
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
|
||||||
|
var args = [];
|
||||||
|
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
|
||||||
|
|
||||||
|
var header = Buffer.from('010100000000000000000000', 'hex');
|
||||||
|
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
|
||||||
|
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
|
||||||
|
this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args , send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]]))});
|
||||||
|
|
||||||
|
if(!this._amt)
|
||||||
|
{
|
||||||
|
this._setupPTHI();
|
||||||
|
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getVersion = function getVersion(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(26, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var i, CodeVersion = header.Data, val = { BiosVersion: CodeVersion.slice(0, this._amt.BiosVersionLen).toString(), Versions: [] }, v = CodeVersion.slice(this._amt.BiosVersionLen + 4);
|
||||||
|
for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen) ; ++i) {
|
||||||
|
val.Versions[i] = { Description: v.slice(2, v.readUInt16LE(0) + 2).toString(), Version: v.slice(4 + this._amt.UnicodeStringLen, 4 + this._amt.UnicodeStringLen + v.readUInt16LE(2 + this._amt.UnicodeStringLen)).toString() };
|
||||||
|
v = v.slice(4 + (2 * this._amt.UnicodeStringLen));
|
||||||
|
}
|
||||||
|
if (val.BiosVersion.indexOf('\0') > 0) { val.BiosVersion = val.BiosVersion.substring(0, val.BiosVersion.indexOf('\0')); }
|
||||||
|
opt.unshift(val);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getUuid = function getUuid(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x5c, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.uuid = [zeroLeftPad(header.Data.readUInt32LE(0).toString(16), 8),
|
||||||
|
zeroLeftPad(header.Data.readUInt16LE(4).toString(16), 4),
|
||||||
|
zeroLeftPad(header.Data.readUInt16LE(6).toString(16), 4),
|
||||||
|
zeroLeftPad(header.Data.readUInt16BE(8).toString(16), 4),
|
||||||
|
zeroLeftPad(header.Data.slice(10).toString('hex').toLowerCase(), 12)].join('-');
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getProvisioningState = function getProvisioningState(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(17, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.state = header.Data.readUInt32LE(0);
|
||||||
|
if (result.state < 3) { result.stateStr = ["PRE", "IN", "POST"][result.state]; }
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getProvisioningMode = function getProvisioningMode(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(8, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.mode = header.Data.readUInt32LE(0);
|
||||||
|
if (result.mode < 4) { result.modeStr = ["NONE", "ENTERPRISE", "SMALL_BUSINESS", "REMOTE_ASSISTANCE"][result.mode]; }
|
||||||
|
result.legacy = header.Data.readUInt32LE(4) == 0 ? false : true;
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getEHBCState = function getEHBCState(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(132, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
opt.unshift({ EHBC: header.Data.readUInt32LE(0) != 0 });
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getControlMode = function getControlMode(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(107, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.controlMode = header.Data.readUInt32LE(0);
|
||||||
|
if (result.controlMode < 3) { result.controlModeStr = ["NONE_RPAT", "CLIENT", "ADMIN", "REMOTE_ASSISTANCE"][result.controlMode]; }
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getMACAddresses = function getMACAddresses(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(37, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
opt.unshift({ DedicatedMAC: header.Data.slice(0, 6).toString('hex:'), HostMAC: header.Data.slice(6, 12).toString('hex:') });
|
||||||
|
} else { opt.unshift({ DedicatedMAC: null, HostMAC: null }); }
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getDnsSuffix = function getDnsSuffix(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(54, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var resultLen = header.Data.readUInt16LE(0);
|
||||||
|
if (resultLen > 0) { opt.unshift(header.Data.slice(2, 2 + resultLen).toString()); } else { opt.unshift(null); }
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getHashHandles = function getHashHandles(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x2C, null, function (header, fn, opt) {
|
||||||
|
var result = [];
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var resultLen = header.Data.readUInt32LE(0);
|
||||||
|
for (var i = 0; i < resultLen; ++i) {
|
||||||
|
result.push(header.Data.readUInt32LE(4 + (4 * i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.unshift(result);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getCertHashEntry = function getCertHashEntry(handle, callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
|
||||||
|
var data = Buffer.alloc(4);
|
||||||
|
data.writeUInt32LE(handle, 0);
|
||||||
|
|
||||||
|
this.sendCommand(0x2D, data, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.isDefault = header.Data.readUInt32LE(0);
|
||||||
|
result.isActive = header.Data.readUInt32LE(4);
|
||||||
|
result.hashAlgorithm = header.Data.readUInt8(72);
|
||||||
|
if (result.hashAlgorithm < 4) {
|
||||||
|
result.hashAlgorithmStr = ["MD5", "SHA1", "SHA256", "SHA512"][result.hashAlgorithm];
|
||||||
|
result.hashAlgorithmSize = [16, 20, 32, 64][result.hashAlgorithm];
|
||||||
|
result.certificateHash = header.Data.slice(8, 8 + result.hashAlgorithmSize).toString('hex');
|
||||||
|
}
|
||||||
|
result.name = header.Data.slice(73 + 2, 73 + 2 + header.Data.readUInt16LE(73)).toString();
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getCertHashEntries = function getCertHashEntries(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
|
||||||
|
this.getHashHandles(function (handles, fn, opt) {
|
||||||
|
var entries = [];
|
||||||
|
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getHashEntrySink = function _getHashEntrySink(result, fn, opt, entries, handles) {
|
||||||
|
entries.push(result);
|
||||||
|
if (handles.length > 0) {
|
||||||
|
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
|
||||||
|
} else {
|
||||||
|
opt.unshift(entries);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.getLocalSystemAccount = function getLocalSystemAccount(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt)
|
||||||
|
{
|
||||||
|
if (header.Status == 0 && header.Data.length == 68)
|
||||||
|
{
|
||||||
|
opt.unshift({ user: trim(header.Data.slice(0, 33).toString()), pass: trim(header.Data.slice(33, 67).toString()), raw: header.Data });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
}
|
||||||
|
this.getLanInterfaceSettings = function getLanInterfaceSettings(index, callback)
|
||||||
|
{
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
var ifx = Buffer.alloc(4);
|
||||||
|
ifx.writeUInt32LE(index);
|
||||||
|
this.sendCommand(0x48, ifx, function onGetLanInterfaceSettings(header, fn, opt)
|
||||||
|
{
|
||||||
|
if(header.Status == 0)
|
||||||
|
{
|
||||||
|
var info = {};
|
||||||
|
info.enabled = header.Data.readUInt32LE(0);
|
||||||
|
info.dhcpEnabled = header.Data.readUInt32LE(8);
|
||||||
|
switch(header.Data[12])
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
info.dhcpMode = 'ACTIVE'
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
info.dhcpMode = 'PASSIVE'
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
info.dhcpMode = 'UNKNOWN';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
info.mac = header.Data.slice(14).toString('hex:');
|
||||||
|
|
||||||
|
var addr = header.Data.readUInt32LE(4);
|
||||||
|
info.address = ((addr >> 24) & 255) + '.' + ((addr >> 16) & 255) + '.' + ((addr >> 8) & 255) + '.' + (addr & 255);
|
||||||
|
opt.unshift(info);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt.unshift(null);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}
|
||||||
|
}, callback, optional);
|
||||||
|
|
||||||
|
};
|
||||||
|
this.unprovision = function unprovision(mode, callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
var data = Buffer.alloc(4);
|
||||||
|
data.writeUInt32LE(mode, 0);
|
||||||
|
this.sendCommand(16, data, function (header, fn, opt) {
|
||||||
|
opt.unshift(header.Status);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
}
|
||||||
|
this.startConfiguration = function startConfiguration() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x29, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.stopConfiguration = function stopConfiguration() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x5E, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.openUserInitiatedConnection = function openUserInitiatedConnection() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x44, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.closeUserInitiatedConnection = function closeUnserInitiatedConnected() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x45, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.getRemoteAccessConnectionStatus = function getRemoteAccessConnectionStatus() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x46, data, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var hostname = v.slice(14, header.Data.readUInt16LE(12) + 14).toString()
|
||||||
|
opt.unshift({ status: header.Status, networkStatus: header.Data.readUInt32LE(0), remoteAccessStatus: header.Data.readUInt32LE(4), remoteAccessTrigger: header.Data.readUInt32LE(8), mpsHostname: hostname, raw: header.Data });
|
||||||
|
} else {
|
||||||
|
opt.unshift({ status: header.Status });
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
}
|
||||||
|
this.getProtocolVersion = function getProtocolVersion(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
|
||||||
|
|
||||||
|
heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
|
||||||
|
if (status == 0) {
|
||||||
|
var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
|
||||||
|
opt.unshift(result);
|
||||||
|
fn.apply(self, opt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opt.unshift(null);
|
||||||
|
fn.apply(self, opt);
|
||||||
|
}
|
||||||
|
}, this, callback, optional);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = amt_heci;
|
105
agents-new/modules_meshcmd/amt-scanner.js
Normal file
105
agents-new/modules_meshcmd/amt-scanner.js
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Meshcentral Intel AMT Local Scanner
|
||||||
|
* @author Ylian Saint-Hilaire & Joko Sastriawan
|
||||||
|
* @version v0.0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Construct a Intel AMT Scanner object
|
||||||
|
|
||||||
|
function AMTScanner() {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('found');
|
||||||
|
|
||||||
|
this.dgram = require('dgram');
|
||||||
|
|
||||||
|
this.buildRmcpPing = function (tag) {
|
||||||
|
var packet = Buffer.from('06000006000011BE80000000', 'hex');
|
||||||
|
packet[9] = tag;
|
||||||
|
return packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.parseRmcpPacket = function (server, data, rinfo, func) {
|
||||||
|
if (data == null || data.length < 20) return;
|
||||||
|
var res = {};
|
||||||
|
if (((data[12] == 0) || (data[13] != 0) || (data[14] != 1) || (data[15] != 0x57)) && (data[21] & 32)) {
|
||||||
|
res.servertag = data[9];
|
||||||
|
res.minorVersion = data[18] & 0x0F;
|
||||||
|
res.majorVersion = (data[18] >> 4) & 0x0F;
|
||||||
|
res.provisioningState = data[19] & 0x03; // Pre = 0, In = 1, Post = 2
|
||||||
|
|
||||||
|
var openPort = (data[16] * 256) + data[17];
|
||||||
|
var dualPorts = ((data[19] & 0x04) != 0) ? true : false;
|
||||||
|
res.openPorts = [openPort];
|
||||||
|
res.address = rinfo.address;
|
||||||
|
if (dualPorts == true) { res.openPorts = [16992, 16993]; }
|
||||||
|
if (func !== undefined) {
|
||||||
|
func(server, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parseIPv4Range = function (range) {
|
||||||
|
if (range == undefined || range == null) return null;
|
||||||
|
var x = range.split('-');
|
||||||
|
if (x.length == 2) { return { min: this.parseIpv4Addr(x[0]), max: this.parseIpv4Addr(x[1]) }; }
|
||||||
|
x = range.split('/');
|
||||||
|
if (x.length == 2) {
|
||||||
|
var ip = this.parseIpv4Addr(x[0]), masknum = parseInt(x[1]), mask = 0;
|
||||||
|
if (masknum <= 16 || masknum > 32) return null;
|
||||||
|
masknum = 32 - masknum;
|
||||||
|
for (var i = 0; i < masknum; i++) { mask = (mask << 1); mask++; }
|
||||||
|
return { min: ip & (0xFFFFFFFF - mask), max: (ip & (0xFFFFFFFF - mask)) + mask };
|
||||||
|
}
|
||||||
|
x = this.parseIpv4Addr(range);
|
||||||
|
if (x == null) return null;
|
||||||
|
return { min: x, max: x };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse IP address. Takes a
|
||||||
|
this.parseIpv4Addr = function (addr) {
|
||||||
|
var x = addr.split('.');
|
||||||
|
if (x.length == 4) { return (parseInt(x[0]) << 24) + (parseInt(x[1]) << 16) + (parseInt(x[2]) << 8) + (parseInt(x[3]) << 0); }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP address number to string
|
||||||
|
this.IPv4NumToStr = function (num) {
|
||||||
|
return ((num >> 24) & 0xFF) + '.' + ((num >> 16) & 0xFF) + '.' + ((num >> 8) & 0xFF) + '.' + (num & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scan = function (rangestr, timeout) {
|
||||||
|
var iprange = this.parseIPv4Range(rangestr);
|
||||||
|
var rmcp = this.buildRmcpPing(0);
|
||||||
|
var server = this.dgram.createSocket({ type: 'udp4' });
|
||||||
|
server.parent = this;
|
||||||
|
server.scanResults = [];
|
||||||
|
server.on('error', function (err) { console.log('Error:' + err); });
|
||||||
|
server.on('message', function (msg, rinfo) { if (rinfo.size > 4) { this.parent.parseRmcpPacket(this, msg, rinfo, function (s, res) { s.scanResults.push(res); }) }; });
|
||||||
|
server.on('listening', function () { for (var i = iprange.min; i <= iprange.max; i++) { server.send(rmcp, 623, server.parent.IPv4NumToStr(i)); } });
|
||||||
|
server.bind({ address: '0.0.0.0', port: 0, exclusive: true });
|
||||||
|
var tmout = setTimeout(function cb() {
|
||||||
|
//console.log("Server closed");
|
||||||
|
server.close();
|
||||||
|
server.parent.emit('found', server.scanResults);
|
||||||
|
delete server;
|
||||||
|
}, timeout);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AMTScanner;
|
401
agents-new/modules_meshcmd/amt-script.js
Normal file
401
agents-new/modules_meshcmd/amt-script.js
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Script Compiler / Decompiler / Runner
|
||||||
|
* @author Ylian Saint-Hilaire
|
||||||
|
* @version v0.1.0e
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Core functions
|
||||||
|
script_functionTable1 = ['nop', 'jump', 'set', 'print', 'dialog', 'getitem', 'substr', 'indexof', 'split', 'join', 'length', 'jsonparse', 'jsonstr', 'add', 'substract', 'parseint', 'wsbatchenum', 'wsput', 'wscreate', 'wsdelete', 'wsexec', 'scriptspeed', 'wssubscribe', 'wsunsubscribe', 'readchar', 'signwithdummyca'];
|
||||||
|
|
||||||
|
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
|
||||||
|
script_functionTable2 = ['encodeuri', 'decodeuri', 'passwordcheck', 'atob', 'btoa', 'hex2str', 'str2hex', 'random', 'md5', 'maketoarray', 'readshort', 'readshortx', 'readint', 'readsint', 'readintx', 'shorttostr', 'shorttostrx', 'inttostr', 'inttostrx'];
|
||||||
|
|
||||||
|
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
|
||||||
|
script_functionTableX2 = [encodeURI, decodeURI, passwordcheck, atob, btoa, hex2rstr, rstr2hex, random, rstr_md5, MakeToArray, ReadShort, ReadShortX, ReadInt, ReadSInt, ReadIntX, ShortToStr, ShortToStrX, IntToStr, IntToStrX];
|
||||||
|
|
||||||
|
|
||||||
|
function MakeToArray(v) { if (!v || v == null || typeof v == 'object') return v; return [v]; }
|
||||||
|
function ReadShort(v, p) { return (v[p] << 8) + v[p + 1]; }
|
||||||
|
function ReadShortX(v, p) { return (v[p + 1] << 8) + v[p]; }
|
||||||
|
function ReadInt(v, p) { return (v[p] * 0x1000000) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; } // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
|
||||||
|
function ReadSInt(v, p) { return (v[p] << 24) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; }
|
||||||
|
function ReadIntX(v, p) { return (v[p + 3] * 0x1000000) + (v[p + 2] << 16) + (v[p + 1] << 8) + v[p]; }
|
||||||
|
function ShortToStr(v) { return String.fromCharCode((v >> 8) & 0xFF, v & 0xFF); }
|
||||||
|
function ShortToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF); }
|
||||||
|
function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); }
|
||||||
|
function IntToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); }
|
||||||
|
//function ShortToStr(v) { var b = Buffer.alloc(2); b.writeInt16BE(v); return b; }
|
||||||
|
//function ShortToStrX(v) { var b = Buffer.alloc(2); b.writeInt16LE(v); return b; }
|
||||||
|
//function IntToStr(v) { var b = Buffer.alloc(4); b.writeInt32BE(v); return b; }
|
||||||
|
//function IntToStrX(v) { var b = Buffer.alloc(4); b.writeInt32LE(v); return b; }
|
||||||
|
function btoa(x) { return Buffer.from(x).toString('base64');}
|
||||||
|
function atob(x) { var z = null; try { z = Buffer.from(x, 'base64').toString(); } catch (e) { console.log(e); } return z; }
|
||||||
|
function passwordcheck(p) { if (p.length < 8) return false; var upper = 0, lower = 0, number = 0, nonalpha = 0; for (var i in p) { var c = p.charCodeAt(i); if ((c > 64) && (c < 91)) { upper = 1; } else if ((c > 96) && (c < 123)) { lower = 1; } else if ((c > 47) && (c < 58)) { number = 1; } else { nonalpha = 1; } } return ((upper + lower + number + nonalpha) == 4); }
|
||||||
|
function hex2rstr(x) { Buffer.from(x, 'hex').toString(); }
|
||||||
|
function rstr2hex(x) { Buffer.from(x).toString('hex'); }
|
||||||
|
function random() { return Math.floor(Math.random()*max); }
|
||||||
|
function rstr_md5(str) { return hex2rstr(hex_md5(str)); }
|
||||||
|
function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
|
||||||
|
|
||||||
|
var httpErrorTable = {
|
||||||
|
200: 'OK',
|
||||||
|
401: 'Authentication Error',
|
||||||
|
408: 'Timeout Error',
|
||||||
|
601: 'WSMAN Parsing Error',
|
||||||
|
602: 'Unable to parse HTTP response header',
|
||||||
|
603: 'Unexpected HTTP enum response',
|
||||||
|
604: 'Unexpected HTTP pull response',
|
||||||
|
998: 'Invalid TLS certificate'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the script state
|
||||||
|
module.exports.setup = function(binary, startvars) {
|
||||||
|
var obj = { startvars: startvars, onCompleted: null };
|
||||||
|
if (binary.length < 6) { console.error('Invalid script length'); return null; } // Script must have at least 6 byte header
|
||||||
|
if (ReadInt(binary, 0) != 0x247D2945) { console.error('Invalid binary script'); return null; } // Check the script magic header
|
||||||
|
if (ReadShort(binary, 4) > 1) { console.error('Unsupported script version'); return null; } // Check the script version
|
||||||
|
obj.script = binary.slice(6);
|
||||||
|
|
||||||
|
// Reset the script to the start
|
||||||
|
obj.reset = function (stepspeed) {
|
||||||
|
obj.stop();
|
||||||
|
obj.ip = 0;
|
||||||
|
obj.variables = startvars;
|
||||||
|
obj.state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the script
|
||||||
|
obj.start = function (stepspeed) {
|
||||||
|
obj.stop();
|
||||||
|
if (stepspeed == null) { obj.stepspeed = 10; } else { obj.stepspeed = stepspeed; }
|
||||||
|
if (obj.stepspeed > 0) { obj.timer = setInterval(function () { obj.step() }, obj.stepspeed); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the script
|
||||||
|
obj.stop = function () {
|
||||||
|
if (obj.timer != null) { clearInterval(obj.timer); }
|
||||||
|
obj.timer = null;
|
||||||
|
obj.stepspeed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// function used to load and store variable values
|
||||||
|
obj.getVar = function (name) { if (name == undefined) return undefined; return obj.getVarEx(name.split('.'), obj.variables); }
|
||||||
|
obj.getVarEx = function (name, val) { try { if (name == undefined) return undefined; if (name.length == 0) return val; return obj.getVarEx(name.slice(1), val[name[0]]); } catch (e) { return null; } }
|
||||||
|
obj.setVar = function (name, val) { obj.setVarEx(name.split('.'), obj.variables, val); }
|
||||||
|
obj.setVarEx = function (name, vars, val) { if (name.length == 1) { vars[name[0]] = val; } else { obj.setVarEx(name.slice(1), vars[name[0]], val); } }
|
||||||
|
|
||||||
|
// Run the script one step forward
|
||||||
|
obj.step = function () {
|
||||||
|
if (obj.state != 1) return;
|
||||||
|
if (obj.ip < obj.script.length) {
|
||||||
|
var cmdid = ReadShort(obj.script, obj.ip);
|
||||||
|
var cmdlen = ReadShort(obj.script, obj.ip + 2);
|
||||||
|
var argcount = ReadShort(obj.script, obj.ip + 4);
|
||||||
|
var argptr = obj.ip + 6;
|
||||||
|
var args = [];
|
||||||
|
|
||||||
|
// Clear all temp variables (This is optional)
|
||||||
|
for (var i in obj.variables) { if (i.startsWith('__')) { delete obj.variables[i]; } }
|
||||||
|
|
||||||
|
// Loop on each argument, moving forward by the argument length each time
|
||||||
|
for (var i = 0; i < argcount; i++) {
|
||||||
|
var arglen = ReadShort(obj.script, argptr);
|
||||||
|
var argval = obj.script.slice(argptr + 2, argptr + 2 + arglen);
|
||||||
|
var argtyp = argval[0];
|
||||||
|
argval = argval.slice(1);
|
||||||
|
if (argtyp < 2) {
|
||||||
|
// Get the value and replace all {var} with variable values
|
||||||
|
argval = argval.toString();
|
||||||
|
while (argval.split("{").length > 1) { var t = argval.split("{").pop().split("}").shift(); argval = argval.replace('{' + t + '}', obj.getVar(t)); }
|
||||||
|
if (argtyp == 1) { obj.variables['__' + i] = decodeURI(argval); argval = '__' + i; } // If argtyp is 1, this is a literal. Store in temp variable.
|
||||||
|
args.push(argval);
|
||||||
|
}
|
||||||
|
if (argtyp == 2 || argtyp == 3) {
|
||||||
|
obj.variables['__' + i] = ReadSInt(argval, 0);
|
||||||
|
args.push('__' + i);
|
||||||
|
}
|
||||||
|
argptr += (2 + arglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move instruction pointer forward by command size
|
||||||
|
obj.ip += cmdlen;
|
||||||
|
|
||||||
|
// Get all variable values
|
||||||
|
var argsval = [];
|
||||||
|
for (var i = 0; i < 10; i++) { argsval.push(obj.getVar(args[i])); }
|
||||||
|
var storeInArg0;
|
||||||
|
try {
|
||||||
|
if (cmdid < 10000) {
|
||||||
|
// Lets run the actual command
|
||||||
|
switch (cmdid) {
|
||||||
|
case 0: // nop
|
||||||
|
break;
|
||||||
|
case 1: // jump(label) or jump(label, a, compare, b)
|
||||||
|
if (argsval[2]) {
|
||||||
|
if (
|
||||||
|
(argsval[2] == '<' && argsval[1] < argsval[3]) ||
|
||||||
|
(argsval[2] == '<=' && argsval[1] <= argsval[3]) ||
|
||||||
|
(argsval[2] == '!=' && argsval[1] != argsval[3]) ||
|
||||||
|
(argsval[2] == '=' && argsval[1] == argsval[3]) ||
|
||||||
|
(argsval[2] == '>=' && argsval[1] >= argsval[3]) ||
|
||||||
|
(argsval[2] == '>' && argsval[1] > argsval[3])
|
||||||
|
) {
|
||||||
|
obj.ip = argsval[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj.ip = argsval[0]; // Set the instruction pointer to the new location in the script
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // set(variable, value)
|
||||||
|
if (args[1] == undefined) delete obj.variables[args[0]]; else obj.setVar(args[0], argsval[1]);
|
||||||
|
break;
|
||||||
|
case 3: // print(message)
|
||||||
|
var v = obj.toString(argsval[0]);
|
||||||
|
if (v.indexOf('INFO: ') == 0) { v = v.substring(6); }
|
||||||
|
if (v.indexOf('SUCCESS: ') == 0) { v = v.substring(9); }
|
||||||
|
if (obj.onConsole) { obj.onConsole(v, obj); } else { console.log(v); }
|
||||||
|
// Q(obj.consoleid).value += () + '\n'); Q(obj.console).scrollTop = Q(obj.console).scrollHeight;
|
||||||
|
break;
|
||||||
|
case 4: // dialog(title, content, buttons)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.dialog = true;
|
||||||
|
setDialogMode(11, argsval[0], argsval[2], obj.xxStepDialogOk, argsval[1], obj);
|
||||||
|
break;
|
||||||
|
case 5: // getitem(a, b, c)
|
||||||
|
for (var i in argsval[1]) { if (argsval[1][i][argsval[2]] == argsval[3]) { storeInArg0 = i; } };
|
||||||
|
break;
|
||||||
|
case 6: // substr(variable_dest, variable_src, index, len)
|
||||||
|
storeInArg0 = argsval[1].substr(argsval[2], argsval[3]);
|
||||||
|
break;
|
||||||
|
case 7: // indexOf(variable_dest, variable_src, index, len)
|
||||||
|
storeInArg0 = argsval[1].indexOf(argsval[2]);
|
||||||
|
break;
|
||||||
|
case 8: // split(variable_dest, variable_src, separator)
|
||||||
|
storeInArg0 = argsval[1].split(argsval[2]);
|
||||||
|
break;
|
||||||
|
case 9: // join(variable_dest, variable_src, separator)
|
||||||
|
storeInArg0 = argsval[1].join(argsval[2]);
|
||||||
|
break;
|
||||||
|
case 10: // length(variable_dest, variable_src)
|
||||||
|
if (argsval[1] == null) { storeInArg0 = 0; } else { storeInArg0 = argsval[1].length; }
|
||||||
|
break;
|
||||||
|
case 11: // jsonparse(variable_dest, json)
|
||||||
|
storeInArg0 = JSON.parse(argsval[1]);
|
||||||
|
break;
|
||||||
|
case 12: // jsonstr(variable_dest, variable_src)
|
||||||
|
storeInArg0 = JSON.stringify(argsval[1]);
|
||||||
|
break;
|
||||||
|
case 13: // add(variable_dest, variable_src, value)
|
||||||
|
storeInArg0 = (argsval[1] + argsval[2]);
|
||||||
|
break;
|
||||||
|
case 14: // substract(variable_dest, variable_src, value)
|
||||||
|
storeInArg0 = (argsval[1] - argsval[2]);
|
||||||
|
break;
|
||||||
|
case 15: // parseInt(variable_dest, variable_src)
|
||||||
|
storeInArg0 = parseInt(argsval[1]);
|
||||||
|
break;
|
||||||
|
case 16: // wsbatchenum(name, objectList)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.BatchEnum(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
|
||||||
|
break;
|
||||||
|
case 17: // wsput(name, args)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.Put(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
|
||||||
|
break;
|
||||||
|
case 18: // wscreate(name, args)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.Create(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
|
||||||
|
break;
|
||||||
|
case 19: // wsdelete(name, args)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.Delete(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
|
||||||
|
break;
|
||||||
|
case 20: // wsexec(name, method, args, selectors)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.Exec(argsval[0], argsval[1], argsval[2], obj.xxWsmanReturn, obj, 0, argsval[3]);
|
||||||
|
break;
|
||||||
|
case 21: // Script Speed
|
||||||
|
obj.stepspeed = argsval[0];
|
||||||
|
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = setInterval(function () { obj.step() }, obj.stepspeed); }
|
||||||
|
break;
|
||||||
|
case 22: // wssubscribe(name, delivery, url, selectors, opaque, user, pass)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.Subscribe(argsval[0], argsval[1], argsval[2], obj.xxWsmanReturn, obj, 0, argsval[3], argsval[4], argsval[5], argsval[6]);
|
||||||
|
break;
|
||||||
|
case 23: // wsunsubscribe(name, selectors)
|
||||||
|
obj.state = 2;
|
||||||
|
obj.amtstack.UnSubscribe(argsval[0], obj.xxWsmanReturn, obj, 0, argsval[1]);
|
||||||
|
break;
|
||||||
|
case 24: // readchar(str, pos)
|
||||||
|
console.log(argsval[1], argsval[2], argsval[1].charCodeAt(argsval[2]));
|
||||||
|
storeInArg0 = argsval[1].charCodeAt(argsval[2]);
|
||||||
|
break;
|
||||||
|
case 25: // signWithDummyCa
|
||||||
|
// Not supported
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
obj.state = 9;
|
||||||
|
console.error("Script Error, unknown command: " + cmdid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cmdid < 20000) {
|
||||||
|
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
|
||||||
|
storeInArg0 = script_functionTableX2[cmdid - 10000](argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]);
|
||||||
|
} else {
|
||||||
|
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
|
||||||
|
//if (script_functionTableX3 && script_functionTableX3[cmdid - 20000]) {
|
||||||
|
// storeInArg0 = script_functionTableX3[cmdid - 20000](obj, argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]); // Note that optional calls start with "obj" as first argument.
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (storeInArg0 != undefined) obj.setVar(args[0], storeInArg0);
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof e == 'object') { e = e.message; }
|
||||||
|
obj.setVar('_exception', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.state == 1 && obj.ip >= obj.script.length) { obj.state = 0; obj.stop(); if (obj.onCompleted) { obj.onCompleted(); } }
|
||||||
|
if (obj.onStep) obj.onStep(obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.xxStepDialogOk = function (button) {
|
||||||
|
obj.variables['DialogSelect'] = button;
|
||||||
|
obj.state = 1;
|
||||||
|
obj.dialog = false;
|
||||||
|
if (obj.onStep) obj.onStep(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.xxWsmanReturn = function (stack, name, responses, status) {
|
||||||
|
obj.setVar(name, responses);
|
||||||
|
obj.setVar('wsman_result', status);
|
||||||
|
obj.setVar('wsman_result_str', ((httpErrorTable[status]) ? (httpErrorTable[status]) : ('Error #' + status)));
|
||||||
|
obj.state = 1;
|
||||||
|
if (obj.onStep) obj.onStep(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.toString = function (x) { if (typeof x == 'object') return JSON.stringify(x); return x; }
|
||||||
|
|
||||||
|
obj.reset();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Argument types: 0 = Variable, 1 = String, 2 = Integer, 3 = Label
|
||||||
|
module.exports.compile = function(script, onmsg) {
|
||||||
|
var r = '', scriptlines = script.split('\n'), labels = {}, labelswap = [], swaps = [];
|
||||||
|
// Go thru each script line and encode it
|
||||||
|
for (var i in scriptlines) {
|
||||||
|
var scriptline = scriptlines[i];
|
||||||
|
if (scriptline.startsWith('##SWAP ')) { var x = scriptline.split(' '); if (x.length == 3) { swaps[x[1]] = x[2]; } } // Add a swap instance
|
||||||
|
if (scriptline[0] == '#' || scriptline.length == 0) continue; // Skip comments & blank lines
|
||||||
|
for (var x in swaps) { scriptline = scriptline.split(x).join(swaps[x]); } // Apply all swaps
|
||||||
|
var keywords = scriptline.match(/"[^"]*"|[^\s"]+/g);
|
||||||
|
if (keywords.length == 0) continue; // Skip blank lines
|
||||||
|
if (scriptline[0] == ':') { labels[keywords[0].toUpperCase()] = r.length; continue; } // Mark a label position
|
||||||
|
var funcIndex = script_functionTable1.indexOf(keywords[0].toLowerCase());
|
||||||
|
if (funcIndex == -1) { funcIndex = script_functionTable2.indexOf(keywords[0].toLowerCase()); if (funcIndex >= 0) funcIndex += 10000; }
|
||||||
|
if (funcIndex == -1) { if (onmsg) { onmsg("Unabled to compile, unknown command: " + keywords[0]); } return ''; }
|
||||||
|
// Encode CommandId, CmdSize, ArgCount, Arg1Len, Arg1, Arg2Len, Arg2...
|
||||||
|
var cmd = ShortToStr(keywords.length - 1);
|
||||||
|
for (var j in keywords) {
|
||||||
|
if (j == 0) continue;
|
||||||
|
if (keywords[j][0] == ':') {
|
||||||
|
labelswap.push([keywords[j], r.length + cmd.length + 7]); // Add a label swap
|
||||||
|
cmd += ShortToStr(5) + String.fromCharCode(3) + IntToStr(0xFFFFFFFF); // Put an empty label
|
||||||
|
} else {
|
||||||
|
var argint = parseInt(keywords[j]);
|
||||||
|
if (argint == keywords[j]) {
|
||||||
|
cmd += ShortToStr(5) + String.fromCharCode(2) + IntToStr(argint);
|
||||||
|
} else {
|
||||||
|
if (keywords[j][0] == '"' && keywords[j][keywords[j].length - 1] == '"') {
|
||||||
|
cmd += ShortToStr(keywords[j].length - 1) + String.fromCharCode(1) + keywords[j].substring(1, keywords[j].length - 1);
|
||||||
|
} else {
|
||||||
|
cmd += ShortToStr(keywords[j].length + 1) + String.fromCharCode(0) + keywords[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd = ShortToStr(funcIndex) + ShortToStr(cmd.length + 4) + cmd;
|
||||||
|
r += cmd;
|
||||||
|
}
|
||||||
|
// Perform all the needed label swaps
|
||||||
|
for (i in labelswap) {
|
||||||
|
var label = labelswap[i][0].toUpperCase(), position = labelswap[i][1], target = labels[label];
|
||||||
|
if (target == undefined) { if (onmsg) { onmsg("Unabled to compile, unknown label: " + label); } return ''; }
|
||||||
|
r = r.substr(0, position) + IntToStr(target) + r.substr(position + 4);
|
||||||
|
}
|
||||||
|
return IntToStr(0x247D2945) + ShortToStr(1) + r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompile the script, intended for debugging only
|
||||||
|
module.exports.decompile = function(binary, onecmd) {
|
||||||
|
var r = '', ptr = 6, labelcount = 0, labels = {};
|
||||||
|
if (onecmd >= 0) {
|
||||||
|
ptr = onecmd; // If we are decompiling just one command, set the ptr to that command.
|
||||||
|
} else {
|
||||||
|
if (binary.length < 6) { return '# Invalid script length'; }
|
||||||
|
var magic = ReadInt(binary, 0);
|
||||||
|
var version = ReadShort(binary, 4);
|
||||||
|
if (magic != 0x247D2945) { return '# Invalid binary script: ' + magic; }
|
||||||
|
if (version != 1) { return '# Invalid script version'; }
|
||||||
|
}
|
||||||
|
// Loop on each command, moving forward by the command length each time.
|
||||||
|
while (ptr < binary.length) {
|
||||||
|
var cmdid = ReadShort(binary, ptr);
|
||||||
|
var cmdlen = ReadShort(binary, ptr + 2);
|
||||||
|
var argcount = ReadShort(binary, ptr + 4);
|
||||||
|
var argptr = ptr + 6;
|
||||||
|
var argstr = '';
|
||||||
|
if (!(onecmd >= 0)) r += ":label" + (ptr - 6) + "\n";
|
||||||
|
// Loop on each argument, moving forward by the argument length each time
|
||||||
|
for (var i = 0; i < argcount; i++) {
|
||||||
|
var arglen = ReadShort(binary, argptr);
|
||||||
|
var argval = binary.substring(argptr + 2, argptr + 2 + arglen);
|
||||||
|
var argtyp = argval.charCodeAt(0);
|
||||||
|
if (argtyp == 0) { argstr += ' ' + argval.substring(1); } // Variable
|
||||||
|
else if (argtyp == 1) { argstr += ' \"' + argval.substring(1) + '\"'; } // String
|
||||||
|
else if (argtyp == 2) { argstr += ' ' + ReadInt(argval, 1); } // Integer
|
||||||
|
else if (argtyp == 3) { // Label
|
||||||
|
var target = ReadInt(argval, 1);
|
||||||
|
var label = labels[target];
|
||||||
|
if (!label) { label = ":label" + target; labels[label] = target; }
|
||||||
|
argstr += ' ' + label;
|
||||||
|
}
|
||||||
|
argptr += (2 + arglen);
|
||||||
|
}
|
||||||
|
// Go in the script function table to decode the function
|
||||||
|
if (cmdid < 10000) {
|
||||||
|
r += script_functionTable1[cmdid] + argstr + "\n";
|
||||||
|
} else {
|
||||||
|
if ((cmdid >= 10000) && (cmdid < 10000)) { r += script_functionTable2[cmdid - 10000] + argstr + "\n"; }
|
||||||
|
}
|
||||||
|
ptr += cmdlen;
|
||||||
|
if (onecmd >= 0) return r; // If we are decompiling just one command, exit now
|
||||||
|
}
|
||||||
|
// Remove all unused labels
|
||||||
|
var scriptlines = r.split('\n');
|
||||||
|
r = '';
|
||||||
|
for (var i in scriptlines) {
|
||||||
|
var line = scriptlines[i];
|
||||||
|
if (line[0] != ':') { r += line + '\n'; } else { if (labels[line]) { r += line + '\n'; } }
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
144
agents-new/modules_meshcmd/amt-wsman-duk.js
Normal file
144
agents-new/modules_meshcmd/amt-wsman-duk.js
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description WSMAN communication using duktape http
|
||||||
|
* @author Ylian Saint-Hilaire
|
||||||
|
* @version v0.2.0c
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Construct a WSMAN communication object
|
||||||
|
function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
|
||||||
|
{
|
||||||
|
var obj = {};
|
||||||
|
obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start.
|
||||||
|
obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls
|
||||||
|
obj.MaxActiveAjaxCount = 1; // Maximum number of activate AJAX calls at the same time.
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (arguments.length == 1 && typeof(arguments[0] == 'object'))
|
||||||
|
{
|
||||||
|
obj.host = arguments[0].host;
|
||||||
|
obj.port = arguments[0].port;
|
||||||
|
obj.authToken = arguments[0].authToken;
|
||||||
|
obj.tls = arguments[0].tls;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj.host = arguments[0];
|
||||||
|
obj.port = arguments[1];
|
||||||
|
obj.user = arguments[2];
|
||||||
|
obj.pass = arguments[3];
|
||||||
|
obj.tls = arguments[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
// pri = priority, if set to 1, the call is high priority and put on top of the stack.
|
||||||
|
obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
|
||||||
|
if ((obj.ActiveAjaxCount == 0 || ((obj.ActiveAjaxCount < obj.MaxActiveAjaxCount) && (obj.challengeParams != null))) && obj.PendingAjax.length == 0) {
|
||||||
|
// There are no pending AJAX calls, perform the call now.
|
||||||
|
obj.PerformAjaxEx(postdata, callback, tag, url, action);
|
||||||
|
} else {
|
||||||
|
// If this is a high priority call, put this call in front of the array, otherwise put it in the back.
|
||||||
|
if (pri == 1) { obj.PendingAjax.unshift([postdata, callback, tag, url, action]); } else { obj.PendingAjax.push([postdata, callback, tag, url, action]); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.PerformNextAjax = function () {
|
||||||
|
if (obj.ActiveAjaxCount >= obj.MaxActiveAjaxCount || obj.PendingAjax.length == 0) return;
|
||||||
|
var x = obj.PendingAjax.shift();
|
||||||
|
obj.PerformAjaxEx(x[0], x[1], x[2], x[3], x[4]);
|
||||||
|
obj.PerformNextAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.PerformAjaxEx = function (postdata, callback, tag, url, action) {
|
||||||
|
if (obj.FailAllError != 0) { if (obj.FailAllError != 999) { obj.gotNextMessagesError({ status: obj.FailAllError }, 'error', null, [postdata, callback, tag]); } return; }
|
||||||
|
if (!postdata) postdata = "";
|
||||||
|
//console.log("SEND: " + postdata); // DEBUG
|
||||||
|
|
||||||
|
// We are in a DukTape environement
|
||||||
|
if (obj.digest == null)
|
||||||
|
{
|
||||||
|
if (obj.authToken)
|
||||||
|
{
|
||||||
|
obj.digest = require('http-digest').create({ authToken: obj.authToken });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj.digest = require('http-digest').create(obj.user, obj.pass);
|
||||||
|
}
|
||||||
|
obj.digest.http = require('http');
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
//console.log('Request ' + (obj.RequestCount++));
|
||||||
|
req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
|
||||||
|
req.on('response', function (response) {
|
||||||
|
//console.log('Response: ' + response.statusCode);
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
//console.log('ERR:' + JSON.stringify(response));
|
||||||
|
obj.gotNextMessagesError({ status: response.statusCode }, 'error', null, [postdata, callback, tag]);
|
||||||
|
} else {
|
||||||
|
response.acc = '';
|
||||||
|
response.on('data', function (data2) { this.acc += data2; });
|
||||||
|
response.on('end', function () { obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send POST body, this work with binary.
|
||||||
|
req.end(postdata);
|
||||||
|
obj.ActiveAjaxCount++;
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AJAX specific private method
|
||||||
|
obj.pendingAjaxCall = [];
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.gotNextMessages = function (data, status, request, callArgs) {
|
||||||
|
obj.ActiveAjaxCount--;
|
||||||
|
if (obj.FailAllError == 999) return;
|
||||||
|
//console.log("RECV: " + data); // DEBUG
|
||||||
|
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
|
||||||
|
if (request.status != 200) { callArgs[1](null, request.status, callArgs[2]); return; }
|
||||||
|
callArgs[1](data, 200, callArgs[2]);
|
||||||
|
obj.PerformNextAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.gotNextMessagesError = function (request, status, errorThrown, callArgs) {
|
||||||
|
obj.ActiveAjaxCount--;
|
||||||
|
if (obj.FailAllError == 999) return;
|
||||||
|
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
|
||||||
|
//if (status != 200) { console.log("ERROR, status=" + status + "\r\n\r\nreq=" + callArgs[0]); } // Debug: Display the request & response if something did not work.
|
||||||
|
if (obj.FailAllError != 999) { callArgs[1]({ Header: { HttpError: request.status } }, request.status, callArgs[2]); }
|
||||||
|
obj.PerformNextAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel all pending queries with given status
|
||||||
|
obj.CancelAllQueries = function (s) {
|
||||||
|
while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CreateWsmanComm;
|
211
agents-new/modules_meshcmd/amt-wsman.js
Normal file
211
agents-new/modules_meshcmd/amt-wsman.js
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Intel(r) AMT WSMAN Stack
|
||||||
|
* @author Ylian Saint-Hilaire
|
||||||
|
* @version v0.2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Construct a MeshServer object
|
||||||
|
function WsmanStackCreateService(/*CreateWsmanComm, host, port, user, pass, tls, extra*/)
|
||||||
|
{
|
||||||
|
var obj = {_ObjectID: 'WSMAN'};
|
||||||
|
//obj.onDebugMessage = null; // Set to a function if you want to get debug messages.
|
||||||
|
obj.NextMessageId = 1; // Next message number, used to label WSMAN calls.
|
||||||
|
obj.Address = '/wsman';
|
||||||
|
obj.xmlParser = require('amt-xml');
|
||||||
|
|
||||||
|
if (arguments.length == 1 && typeof (arguments[0] == 'object'))
|
||||||
|
{
|
||||||
|
var CreateWsmanComm = arguments[0].transport;
|
||||||
|
if (CreateWsmanComm) { obj.comm = new CreateWsmanComm(arguments[0]); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var CreateWsmanComm = arguments[0];
|
||||||
|
if (CreateWsmanComm) { obj.comm = new CreateWsmanComm(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.PerformAjax = function PerformAjax(postdata, callback, tag, pri, namespaces) {
|
||||||
|
if (namespaces == null) namespaces = '';
|
||||||
|
obj.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns=\"http://www.w3.org/2003/05/soap-envelope\" ' + namespaces + '><Header><a:Action>' + postdata, function (data, status, tag) {
|
||||||
|
if (status != 200) { callback(obj, null, { Header: { HttpError: status } }, status, tag); return; }
|
||||||
|
var wsresponse = obj.xmlParser.ParseWsman(data);
|
||||||
|
if (!wsresponse || wsresponse == null) { callback(obj, null, { Header: { HttpError: status } }, 601, tag); } else { callback(obj, wsresponse.Header["ResourceURI"], wsresponse, 200, tag); }
|
||||||
|
}, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
//obj.Debug = function (msg) { /*console.log(msg);*/ }
|
||||||
|
|
||||||
|
// Cancel all pending queries with given status
|
||||||
|
obj.CancelAllQueries = function CancelAllQueries(s) { obj.comm.CancelAllQueries(s); }
|
||||||
|
|
||||||
|
// Get the last element of a URI string
|
||||||
|
obj.GetNameFromUrl = function (resuri) {
|
||||||
|
var x = resuri.lastIndexOf("/");
|
||||||
|
return (x == -1)?resuri:resuri.substring(x + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN Subscribe operation
|
||||||
|
obj.ExecSubscribe = function ExecSubscribe(resuri, delivery, url, callback, tag, pri, selectors, opaque, user, pass) {
|
||||||
|
var digest = "", digest2 = "", opaque = "";
|
||||||
|
if (user != null && pass != null) { digest = '<t:IssuedTokens xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>' + user + '</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">' + pass + '</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>'; digest2 = '<w:Auth Profile="http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/http/digest"/>'; }
|
||||||
|
if (opaque != null) { opaque = '<a:ReferenceParameters><m:arg>' + opaque + '</m:arg></a:ReferenceParameters>'; }
|
||||||
|
if (delivery == 'PushWithAck') { delivery = 'dmtf.org/wbem/wsman/1/wsman/PushWithAck'; } else if (delivery == 'Push') { delivery = 'xmlsoap.org/ws/2004/08/eventing/DeliveryModes/Push'; }
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>" + _PutObjToSelectorsXml(selectors) + digest + '</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.' + delivery + '"><e:NotifyTo><a:Address>' + url + '</a:Address>' + opaque + '</e:NotifyTo>' + digest2 + '</e:Delivery></e:Subscribe>';
|
||||||
|
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:m="http://x.com"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN UnSubscribe operation
|
||||||
|
obj.ExecUnSubscribe = function ExecUnSubscribe(resuri, callback, tag, pri, selectors) {
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>" + _PutObjToSelectorsXml(selectors) + '</Header><Body><e:Unsubscribe/>';
|
||||||
|
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN PUT operation
|
||||||
|
obj.ExecPut = function ExecPut(resuri, putobj, callback, tag, pri, selectors) {
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + '</Header><Body>' + _PutObjToBodyXml(resuri, putobj);
|
||||||
|
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN CREATE operation
|
||||||
|
obj.ExecCreate = function ExecCreate(resuri, putobj, callback, tag, pri, selectors) {
|
||||||
|
var objname = obj.GetNameFromUrl(resuri);
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + "</Header><Body><g:" + objname + " xmlns:g=\"" + resuri + "\">";
|
||||||
|
for (var n in putobj) { data += "<g:" + n + ">" + putobj[n] + "</g:" + n + ">" }
|
||||||
|
obj.PerformAjax(data + "</g:" + objname + "></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN DELETE operation
|
||||||
|
obj.ExecDelete = function ExecDelete(resuri, putobj, callback, tag, pri) {
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(putobj) + "</Header><Body /></Envelope>";
|
||||||
|
obj.PerformAjax(data, callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN GET operation
|
||||||
|
obj.ExecGet = function ExecGet(resuri, callback, tag, pri) {
|
||||||
|
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN method call operation
|
||||||
|
obj.ExecMethod = function ExecMethod(resuri, method, args, callback, tag, pri, selectors) {
|
||||||
|
var argsxml = "";
|
||||||
|
for (var i in args) { if (args[i] != null) { if (Array.isArray(args[i])) { for (var x in args[i]) { argsxml += "<r:" + i + ">" + args[i][x] + "</r:" + i + ">"; } } else { argsxml += "<r:" + i + ">" + args[i] + "</r:" + i + ">"; } } }
|
||||||
|
obj.ExecMethodXml(resuri, method, argsxml, callback, tag, pri, selectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN method call operation. The arguments are already formatted in XML.
|
||||||
|
obj.ExecMethodXml = function ExecMethodXml(resuri, method, argsxml, callback, tag, pri, selectors) {
|
||||||
|
obj.PerformAjax(resuri + "/" + method + "</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + "</Header><Body><r:" + method + '_INPUT' + " xmlns:r=\"" + resuri + "\">" + argsxml + "</r:" + method + "_INPUT></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN ENUM operation
|
||||||
|
obj.ExecEnum = function ExecEnum(resuri, callback, tag, pri) {
|
||||||
|
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\" /></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN PULL operation
|
||||||
|
obj.ExecPull = function ExecPull(resuri, enumctx, callback, tag, pri) {
|
||||||
|
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\"><EnumerationContext>" + enumctx + "</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _PutObjToBodyXml(resuri, putObj) {
|
||||||
|
if (!resuri || putObj == null) return '';
|
||||||
|
var objname = obj.GetNameFromUrl(resuri);
|
||||||
|
var result = '<r:' + objname + ' xmlns:r="' + resuri + '">';
|
||||||
|
|
||||||
|
for (var prop in putObj) {
|
||||||
|
if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue;
|
||||||
|
if (putObj[prop] == null || typeof putObj[prop] === 'function') continue;
|
||||||
|
if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) {
|
||||||
|
result += '<r:' + prop + '><a:Address>' + putObj[prop].Address + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + putObj[prop]['ReferenceParameters']["ResourceURI"] + '</w:ResourceURI><w:SelectorSet>';
|
||||||
|
var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector'];
|
||||||
|
if (Array.isArray(selectorArray)) {
|
||||||
|
for (var i=0; i< selectorArray.length; i++) {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet></a:ReferenceParameters></r:' + prop + '>';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Array.isArray(putObj[prop])) {
|
||||||
|
for (var i = 0; i < putObj[prop].length; i++) {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop][i].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += '</r:' + objname + '>';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
convert
|
||||||
|
{ @Name: 'InstanceID', @AttrName: 'Attribute Value'}
|
||||||
|
into
|
||||||
|
' Name="InstanceID" AttrName="Attribute Value" '
|
||||||
|
*/
|
||||||
|
function _ObjectToXmlAttributes(objWithAttributes) {
|
||||||
|
if(!objWithAttributes) return '';
|
||||||
|
var result = ' ';
|
||||||
|
for (var propName in objWithAttributes) {
|
||||||
|
if (!objWithAttributes.hasOwnProperty(propName) || propName.indexOf('@') !== 0) continue;
|
||||||
|
result += propName.substring(1) + '="' + objWithAttributes[propName] + '" ';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _PutObjToSelectorsXml(selectorSet) {
|
||||||
|
if (!selectorSet) return '';
|
||||||
|
if (typeof selectorSet == 'string') return selectorSet;
|
||||||
|
if (selectorSet['InstanceID']) return "<w:SelectorSet><w:Selector Name=\"InstanceID\">" + selectorSet['InstanceID'] + "</w:Selector></w:SelectorSet>";
|
||||||
|
var result = '<w:SelectorSet>';
|
||||||
|
for(var propName in selectorSet) {
|
||||||
|
if (!selectorSet.hasOwnProperty(propName)) continue;
|
||||||
|
result += '<w:Selector Name="' + propName + '">';
|
||||||
|
if (selectorSet[propName]['ReferenceParameters']) {
|
||||||
|
result += '<a:EndpointReference>';
|
||||||
|
result += '<a:Address>' + selectorSet[propName]['Address'] + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + selectorSet[propName]['ReferenceParameters']['ResourceURI'] + '</w:ResourceURI><w:SelectorSet>';
|
||||||
|
var selectorArray = selectorSet[propName]['ReferenceParameters']['SelectorSet']['Selector'];
|
||||||
|
if (Array.isArray(selectorArray)) {
|
||||||
|
for (var i = 0; i < selectorArray.length; i++) {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>';
|
||||||
|
} else {
|
||||||
|
result += selectorSet[propName];
|
||||||
|
}
|
||||||
|
result += '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet>';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WsmanStackCreateService;
|
185
agents-new/modules_meshcmd/amt-xml.js
Normal file
185
agents-new/modules_meshcmd/amt-xml.js
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Parse XML and return JSON
|
||||||
|
module.exports.ParseWsman = function (xml) {
|
||||||
|
try {
|
||||||
|
if (!xml.childNodes) xml = _turnToXml(xml);
|
||||||
|
var r = { Header: {} }, header = xml.getElementsByTagName("Header")[0], t;
|
||||||
|
if (!header) header = xml.getElementsByTagName("a:Header")[0];
|
||||||
|
if (!header) return null;
|
||||||
|
for (var i = 0; i < header.childNodes.length; i++) {
|
||||||
|
var child = header.childNodes[i];
|
||||||
|
r.Header[child.localName] = child.textContent;
|
||||||
|
}
|
||||||
|
var body = xml.getElementsByTagName("Body")[0];
|
||||||
|
if (!body) body = xml.getElementsByTagName("a:Body")[0];
|
||||||
|
if (!body) return null;
|
||||||
|
if (body.childNodes.length > 0) {
|
||||||
|
t = body.childNodes[0].localName;
|
||||||
|
if (t.indexOf("_OUTPUT") == t.length - 7) { t = t.substring(0, t.length - 7); }
|
||||||
|
r.Header['Method'] = t;
|
||||||
|
r.Body = _ParseWsmanRec(body.childNodes[0]);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Unable to parse XML: " + xml, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
function _ParseWsmanRec(node) {
|
||||||
|
var data, r = {};
|
||||||
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
|
var child = node.childNodes[i];
|
||||||
|
if ((child.childElementCount == null) || (child.childElementCount == 0)) { data = child.textContent; } else { data = _ParseWsmanRec(child); }
|
||||||
|
if (data == 'true') data = true; // Convert 'true' into true
|
||||||
|
if (data == 'false') data = false; // Convert 'false' into false
|
||||||
|
if ((parseInt(data) + '') === data) data = parseInt(data); // Convert integers
|
||||||
|
|
||||||
|
var childObj = data;
|
||||||
|
if ((child.attributes != null) && (child.attributes.length > 0)) {
|
||||||
|
childObj = { 'Value': data };
|
||||||
|
for (var j = 0; j < child.attributes.length; j++) {
|
||||||
|
childObj['@' + child.attributes[j].name] = child.attributes[j].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r[child.localName] instanceof Array) { r[child.localName].push(childObj); }
|
||||||
|
else if (r[child.localName] == null) { r[child.localName] = childObj; }
|
||||||
|
else { r[child.localName] = [r[child.localName], childObj]; }
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _PutObjToBodyXml(resuri, putObj) {
|
||||||
|
if (!resuri || putObj == null) return '';
|
||||||
|
var objname = obj.GetNameFromUrl(resuri);
|
||||||
|
var result = '<r:' + objname + ' xmlns:r="' + resuri + '">';
|
||||||
|
|
||||||
|
for (var prop in putObj) {
|
||||||
|
if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue;
|
||||||
|
if (putObj[prop] == null || typeof putObj[prop] === 'function') continue;
|
||||||
|
if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) {
|
||||||
|
result += '<r:' + prop + '><a:Address>' + putObj[prop].Address + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + putObj[prop]['ReferenceParameters']["ResourceURI"] + '</w:ResourceURI><w:SelectorSet>';
|
||||||
|
var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector'];
|
||||||
|
if (Array.isArray(selectorArray)) {
|
||||||
|
for (var i = 0; i < selectorArray.length; i++) {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet></a:ReferenceParameters></r:' + prop + '>';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Array.isArray(putObj[prop])) {
|
||||||
|
for (var i = 0; i < putObj[prop].length; i++) {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop][i].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += '</r:' + objname + '>';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a drop-in replacement to _turnToXml() that works without xml parser dependency.
|
||||||
|
function _treeBuilder() {
|
||||||
|
this.tree = [];
|
||||||
|
this.push = function (element) { this.tree.push(element); };
|
||||||
|
this.pop = function () { var element = this.tree.pop(); if (this.tree.length > 0) { var x = this.tree.peek(); x.childNodes.push(element); x.childElementCount = x.childNodes.length; } return (element); };
|
||||||
|
this.peek = function () { return (this.tree.peek()); }
|
||||||
|
this.addNamespace = function (prefix, namespace) { this.tree.peek().nsTable[prefix] = namespace; if (this.tree.peek().attributes.length > 0) { for (var i = 0; i < this.tree.peek().attributes; ++i) { var a = this.tree.peek().attributes[i]; if (prefix == '*' && a.name == a.localName) { a.namespace = namespace; } else if (prefix != '*' && a.name != a.localName) { var pfx = a.name.split(':')[0]; if (pfx == prefix) { a.namespace = namespace; } } } } }
|
||||||
|
this.getNamespace = function (prefix) { for (var i = this.tree.length - 1; i >= 0; --i) { if (this.tree[i].nsTable[prefix] != null) { return (this.tree[i].nsTable[prefix]); } } return null; }
|
||||||
|
}
|
||||||
|
function _turnToXml(text) { if (text == null) return null; return ({ childNodes: [_turnToXmlRec(text)], getElementsByTagName: _getElementsByTagName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS }); }
|
||||||
|
function _getElementsByTagNameNS(ns, name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name && (node.namespace == ns || ns == '*')) { ret.push(node); } }); return ret; }
|
||||||
|
function _getElementsByTagName(name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name) { ret.push(node); } }); return ret; }
|
||||||
|
function _getChildElementsByTagName(name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name) { ret.push(this.childNodes[node]); } } } return (ret); }
|
||||||
|
function _getChildElementsByTagNameNS(ns, name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name && (ns == '*' || this.childNodes[node].namespace == ns)) { ret.push(this.childNodes[node]); } } } return (ret); }
|
||||||
|
function _xmlTraverseAllRec(nodes, func) { for (var i in nodes) { func(nodes[i]); if (nodes[i].childNodes) { _xmlTraverseAllRec(nodes[i].childNodes, func); } } }
|
||||||
|
function _turnToXmlRec(text) {
|
||||||
|
var elementStack = new _treeBuilder(), lastElement = null, x1 = text.split('<'), ret = [], element = null, currentElementName = null;
|
||||||
|
for (var i in x1) {
|
||||||
|
var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0];
|
||||||
|
if ((elementName.length > 0) && (elementName[0] != '?')) {
|
||||||
|
if (elementName[0] != '/') {
|
||||||
|
var attributes = [], localName, localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0];
|
||||||
|
Object.defineProperty(attributes, "get",
|
||||||
|
{
|
||||||
|
value: function () {
|
||||||
|
if (arguments.length == 1) {
|
||||||
|
for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } }
|
||||||
|
}
|
||||||
|
else if (arguments.length == 2) {
|
||||||
|
for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ('attributes.get(): Invalid number of parameters');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} });
|
||||||
|
// Parse Attributes
|
||||||
|
if (x3.length > 0) {
|
||||||
|
var skip = false;
|
||||||
|
for (var j in x3) {
|
||||||
|
if (x3[j] == '/') {
|
||||||
|
// This is an empty Element
|
||||||
|
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||||
|
elementStack.peek().textContent = '';
|
||||||
|
lastElement = elementStack.pop();
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var k = x3[j].indexOf('=');
|
||||||
|
if (k > 0) {
|
||||||
|
var attrName = x3[j].substring(0, k);
|
||||||
|
var attrValue = x3[j].substring(k + 2, x3[j].length - 1);
|
||||||
|
var attrNS = elementStack.getNamespace('*');
|
||||||
|
|
||||||
|
if (attrName == 'xmlns') {
|
||||||
|
elementStack.addNamespace('*', attrValue);
|
||||||
|
attrNS = attrValue;
|
||||||
|
} else if (attrName.startsWith('xmlns:')) {
|
||||||
|
elementStack.addNamespace(attrName.substring(6), attrValue);
|
||||||
|
} else {
|
||||||
|
var ax = attrName.split(':');
|
||||||
|
if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); }
|
||||||
|
}
|
||||||
|
var x = { name: attrName, value: attrValue }
|
||||||
|
if (attrNS != null) x.namespace = attrNS;
|
||||||
|
elementStack.peek().attributes.push(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip) { continue; }
|
||||||
|
}
|
||||||
|
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||||
|
if (x2[1]) { elementStack.peek().textContent = x2[1]; }
|
||||||
|
} else { lastElement = elementStack.pop(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastElement;
|
||||||
|
}
|
1017
agents-new/modules_meshcmd/amt.js
Normal file
1017
agents-new/modules_meshcmd/amt.js
Normal file
File diff suppressed because it is too large
Load Diff
389
agents-new/modules_meshcmd/service-host.js
Normal file
389
agents-new/modules_meshcmd/service-host.js
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
var SERVICE_WIN32 = 0x00000010 | 0x00000020;
|
||||||
|
var SERVICE_STATE = { STOPPED: 0x00000001, SERVICE_START_PENDING: 0x00000002, SERVICE_STOP_PENDING: 0x00000003, RUNNING: 0x00000004 };
|
||||||
|
var SERVICE_ACCEPT = { SERVICE_ACCEPT_STOP: 0x00000001, SERVICE_ACCEPT_SHUTDOWN: 0x00000004, SERVICE_ACCEPT_POWEREVENT: 0x00000040, SERVICE_ACCEPT_SESSIONCHANGE: 0x00000080 };
|
||||||
|
|
||||||
|
var SERVICE_CONTROL = { SERVICE_CONTROL_SHUTDOWN: 0x00000005, SERVICE_CONTROL_STOP: 0x00000001, SERVICE_CONTROL_POWEREVENT: 0x0000000D, SERVICE_CONTROL_SESSIONCHANGE: 0x0000000E};
|
||||||
|
var SESSION_CHANGE_TYPE =
|
||||||
|
{
|
||||||
|
WTS_CONSOLE_CONNECT: 0x1,
|
||||||
|
WTS_CONSOLE_DISCONNECT: 0x2,
|
||||||
|
WTS_REMOTE_CONNECT: 0x3,
|
||||||
|
WTS_REMOTE_DISCONNECT: 0x4,
|
||||||
|
WTS_SESSION_LOGON: 0x5,
|
||||||
|
WTS_SESSION_LOGOFF: 0x6,
|
||||||
|
WTS_SESSION_LOCK: 0x7,
|
||||||
|
WTS_SESSION_UNLOCK: 0x8,
|
||||||
|
WTS_SESSION_REMOTE_CONTROL: 0x9,
|
||||||
|
WTS_SESSION_CREATE: 0xa,
|
||||||
|
WTS_SESSION_TERMINATE: 0xb
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var NO_ERROR = 0;
|
||||||
|
|
||||||
|
var serviceManager = require('service-manager');
|
||||||
|
|
||||||
|
function serviceHost(serviceName)
|
||||||
|
{
|
||||||
|
this._ObjectID = 'service-host';
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('serviceStart');
|
||||||
|
emitterUtils.createEvent('serviceStop');
|
||||||
|
emitterUtils.createEvent('normalStart');
|
||||||
|
emitterUtils.createEvent('session');
|
||||||
|
emitterUtils.createEvent('powerStateChange');
|
||||||
|
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this.GM = require('_GenericMarshal');
|
||||||
|
this.Advapi = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this.Advapi.CreateMethod({ method: 'StartServiceCtrlDispatcherA', threadDispatch: 1 });
|
||||||
|
this.Advapi.CreateMethod('RegisterServiceCtrlHandlerExA');
|
||||||
|
this.Advapi.CreateMethod('SetServiceStatus');
|
||||||
|
this.Kernel32 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this.Kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
this.Ole32 = this.GM.CreateNativeProxy('Ole32.dll');
|
||||||
|
this.Ole32.CreateMethod('CoInitializeEx');
|
||||||
|
this.Ole32.CreateMethod('CoUninitialize');
|
||||||
|
|
||||||
|
this._ServiceName = this.GM.CreateVariable(typeof (serviceName) == 'string' ? serviceName : serviceName.name);
|
||||||
|
this._ServiceMain = this.GM.GetGenericGlobalCallback(2);
|
||||||
|
this._ServiceMain.Parent = this;
|
||||||
|
this._ServiceMain.GM = this.GM;
|
||||||
|
this._ServiceMain.on('GlobalCallback', function onGlobalCallback(argc, argv)
|
||||||
|
{
|
||||||
|
//ToDo: Check to make sure this is for us
|
||||||
|
|
||||||
|
this.Parent._ServiceStatus = this.GM.CreateVariable(28);
|
||||||
|
//typedef struct _SERVICE_STATUS {
|
||||||
|
// DWORD dwServiceType;
|
||||||
|
// DWORD dwCurrentState;
|
||||||
|
// DWORD dwControlsAccepted;
|
||||||
|
// DWORD dwWin32ExitCode;
|
||||||
|
// DWORD dwServiceSpecificExitCode;
|
||||||
|
// DWORD dwCheckPoint;
|
||||||
|
// DWORD dwWaitHint;
|
||||||
|
//} SERVICE_STATUS, *LPSERVICE_STATUS;
|
||||||
|
|
||||||
|
// Initialise service status
|
||||||
|
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_WIN32);
|
||||||
|
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.SERVICE_STOPPED, 4);
|
||||||
|
this.Parent._ServiceStatusHandle = this.Parent.Advapi.RegisterServiceCtrlHandlerExA(this.Parent._ServiceName, this.Parent._ServiceControlHandler, this.Parent.GM.StashObject(this.Parent._ServiceControlHandler));
|
||||||
|
if(this.Parent._ServiceStatusHandle.Val == 0)
|
||||||
|
{
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service is starting
|
||||||
|
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.SERVICE_START_PENDING, 4);
|
||||||
|
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||||
|
|
||||||
|
// Service running
|
||||||
|
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.RUNNING, 4);
|
||||||
|
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_ACCEPT.SERVICE_ACCEPT_STOP | SERVICE_ACCEPT.SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT.SERVICE_ACCEPT_SESSIONCHANGE, 8);
|
||||||
|
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||||
|
|
||||||
|
this.Parent.Ole32.CoInitializeEx(0, 2);
|
||||||
|
this.Parent.on('~', function OnServiceHostFinalizer()
|
||||||
|
{
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
var Advapi = GM.CreateNativeProxy('Advapi32.dll');
|
||||||
|
Advapi.CreateMethod('SetServiceStatus');
|
||||||
|
|
||||||
|
Kernel32 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||||
|
Kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
var status = GM.CreateVariable(28);
|
||||||
|
|
||||||
|
// Service was stopped
|
||||||
|
status.toBuffer().writeUInt32LE(SERVICE_WIN32);
|
||||||
|
status.toBuffer().writeUInt32LE(0x00000001, 4);
|
||||||
|
status.toBuffer().writeUInt32LE(0, 8);
|
||||||
|
|
||||||
|
Advapi.SetServiceStatus(this._ServiceStatusHandle, status);
|
||||||
|
|
||||||
|
this.Ole32.CoUninitialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.Parent.emit('serviceStart');
|
||||||
|
});
|
||||||
|
this._ServiceControlHandler = this.GM.GetGenericGlobalCallback(4);
|
||||||
|
this._ServiceControlHandler.Parent = this;
|
||||||
|
this._ServiceControlHandler.GM = this.GM;
|
||||||
|
this._ServiceControlHandler.on('GlobalCallback', function onServiceControlHandler(code, eventType, eventData, context)
|
||||||
|
{
|
||||||
|
var j = this.Parent.GM.UnstashObject(context);
|
||||||
|
if (j != null && j == this)
|
||||||
|
{
|
||||||
|
switch (code.Val)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL.SERVICE_CONTROL_SHUTDOWN:
|
||||||
|
case SERVICE_CONTROL.SERVICE_CONTROL_STOP:
|
||||||
|
this.Parent.emit('serviceStop');
|
||||||
|
return;
|
||||||
|
case SERVICE_CONTROL.SERVICE_CONTROL_SESSIONCHANGE:
|
||||||
|
var sessionId = eventData.Deref(4, 4).toBuffer().readUInt32LE();
|
||||||
|
switch(eventType.Val)
|
||||||
|
{
|
||||||
|
case SESSION_CHANGE_TYPE.WTS_SESSION_LOGON:
|
||||||
|
case SESSION_CHANGE_TYPE.WTS_SESSION_LOGOFF:
|
||||||
|
require('user-sessions').emit('changed');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serviceName) { this._ServiceOptions = typeof (serviceName) == 'object' ? serviceName : { name: serviceName }; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Must specify either ServiceName or Options');
|
||||||
|
}
|
||||||
|
if (!this._ServiceOptions.servicePath)
|
||||||
|
{
|
||||||
|
this._ServiceOptions.servicePath = process.execPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.run = function run()
|
||||||
|
{
|
||||||
|
var serviceOperation = 0;
|
||||||
|
|
||||||
|
for(var i = 0; i<process.argv.length; ++i)
|
||||||
|
{
|
||||||
|
switch(process.argv[i])
|
||||||
|
{
|
||||||
|
case '-install':
|
||||||
|
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._svcManager.installService(this._ServiceOptions);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(this._ServiceOptions.name + ' installed');
|
||||||
|
process.exit();
|
||||||
|
break;
|
||||||
|
case '-uninstall':
|
||||||
|
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._svcManager.uninstallService(this._ServiceOptions);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
if (process.platform == 'win32' || process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
// Only do this on Windows/MacOS, becuase Linux is async... It'll complete later
|
||||||
|
console.log(this._ServiceOptions.name + ' uninstalled');
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
i = process.argv.length;
|
||||||
|
serviceOperation = 1;
|
||||||
|
break;
|
||||||
|
case 'start':
|
||||||
|
case '-d':
|
||||||
|
if (process.platform != 'win32') { break; }
|
||||||
|
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||||
|
this._svcManager.getService(this._ServiceOptions.name).start();
|
||||||
|
console.log(this._ServiceOptions.name + ' starting...');
|
||||||
|
process.exit();
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
case '-s':
|
||||||
|
if (process.platform != 'win32') { break; }
|
||||||
|
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||||
|
this._svcManager.getService(this._ServiceOptions.name).stop();
|
||||||
|
console.log(this._ServiceOptions.name + ' stopping...');
|
||||||
|
process.exit();
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
var serviceTable = this.GM.CreateVariable(4 * this.GM.PointerSize);
|
||||||
|
this._ServiceName.pointerBuffer().copy(serviceTable.toBuffer());
|
||||||
|
this._ServiceMain.pointerBuffer().copy(serviceTable.toBuffer(), this.GM.PointerSize);
|
||||||
|
this._sscd = this.Advapi.StartServiceCtrlDispatcherA(serviceTable);
|
||||||
|
this._sscd.parent = this;
|
||||||
|
this._sscd.on('done', function OnStartServiceCtrlDispatcherA(retVal) {
|
||||||
|
if (retVal.Val == 0)
|
||||||
|
{
|
||||||
|
this.parent.emit('normalStart');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (process.platform == 'linux')
|
||||||
|
{
|
||||||
|
var moduleName = this._ServiceOptions ? this._ServiceOptions.name : process.execPath.substring(1 + process.execPath.lastIndexOf('/'));
|
||||||
|
|
||||||
|
for (var i = 0; i < process.argv.length; ++i) {
|
||||||
|
switch (process.argv[i]) {
|
||||||
|
case 'start':
|
||||||
|
case '-d':
|
||||||
|
var child = require('child_process').execFile(process.execPath, [moduleName], { type: require('child_process').SpawnTypes.DETACHED });
|
||||||
|
var pstream = null;
|
||||||
|
try {
|
||||||
|
pstream = require('fs').createWriteStream('/var/run/' + moduleName + '.pid', { flags: 'w' });
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
}
|
||||||
|
if (pstream == null) {
|
||||||
|
pstream = require('fs').createWriteStream('.' + moduleName + '.pid', { flags: 'w' });
|
||||||
|
}
|
||||||
|
pstream.end(child.pid.toString());
|
||||||
|
|
||||||
|
console.log(moduleName + ' started!');
|
||||||
|
process.exit();
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
case '-s':
|
||||||
|
var pid = null;
|
||||||
|
try {
|
||||||
|
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||||
|
require('fs').unlinkSync('/var/run/' + moduleName + '.pid');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
}
|
||||||
|
if (pid == null) {
|
||||||
|
try {
|
||||||
|
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||||
|
require('fs').unlinkSync('.' + moduleName + '.pid');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid) {
|
||||||
|
process.kill(pid);
|
||||||
|
console.log(moduleName + ' stopped');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(moduleName + ' not running');
|
||||||
|
}
|
||||||
|
process.exit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serviceOperation == 0) {
|
||||||
|
// This is non-windows, so we need to check how this binary was started to determine if this was a service start
|
||||||
|
|
||||||
|
// Start by checking if we were started with start/stop
|
||||||
|
var pid = null;
|
||||||
|
try {
|
||||||
|
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
}
|
||||||
|
if (pid == null) {
|
||||||
|
try {
|
||||||
|
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid != null && pid == process.pid) {
|
||||||
|
this.emit('serviceStart');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Now we need to check if we were started with systemd
|
||||||
|
if (require('process-manager').getProcessInfo(1).Name == 'systemd') {
|
||||||
|
this._checkpid = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._checkpid.result = '';
|
||||||
|
this._checkpid.parent = this;
|
||||||
|
this._checkpid.on('exit', function onCheckPIDExit() {
|
||||||
|
var lines = this.result.split('\r\n');
|
||||||
|
for (i in lines) {
|
||||||
|
if (lines[i].startsWith(' Main PID:')) {
|
||||||
|
var tokens = lines[i].split(' ');
|
||||||
|
if (parseInt(tokens[3]) == process.pid) {
|
||||||
|
this.parent.emit('serviceStart');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parent.emit('normalStart');
|
||||||
|
}
|
||||||
|
delete this.parent._checkpid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.parent.emit('normalStart');
|
||||||
|
delete this.parent._checkpid;
|
||||||
|
});
|
||||||
|
this._checkpid.stdout.on('data', function (chunk) { this.parent.result += chunk.toString(); });
|
||||||
|
this._checkpid.stdin.write("systemctl status " + moduleName + " | grep 'Main PID:'\n");
|
||||||
|
this._checkpid.stdin.write('exit\n');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This isn't even a systemd platform, so this couldn't have been a service start
|
||||||
|
this.emit('normalStart');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
// First let's fetch all the PIDs of running services
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('launchctl list\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var p = {};
|
||||||
|
for (i = 1; i < lines.length; ++i)
|
||||||
|
{
|
||||||
|
tokens = lines[i].split('\t');
|
||||||
|
if (tokens[0] && tokens[0] != '-') { p[tokens[0]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p[process.pid.toString()])
|
||||||
|
{
|
||||||
|
// We are a service!
|
||||||
|
this.emit('serviceStart');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.emit('normalStart');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = serviceHost;
|
497
agents-new/modules_meshcmd/service-manager.js
Normal file
497
agents-new/modules_meshcmd/service-manager.js
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
/*
|
||||||
|
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 parseServiceStatus(token)
|
||||||
|
{
|
||||||
|
var j = {};
|
||||||
|
var serviceType = token.Deref(0, 4).IntVal;
|
||||||
|
j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
|
||||||
|
j.isKernelDriver = ((serviceType & 0x00000001) == 0x00000001);
|
||||||
|
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
|
||||||
|
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
|
||||||
|
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
|
||||||
|
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
|
||||||
|
{
|
||||||
|
case 0x00000005:
|
||||||
|
j.state = 'CONTINUE_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000006:
|
||||||
|
j.state = 'PAUSE_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000007:
|
||||||
|
j.state = 'PAUSED';
|
||||||
|
break;
|
||||||
|
case 0x00000004:
|
||||||
|
j.state = 'RUNNING';
|
||||||
|
break;
|
||||||
|
case 0x00000002:
|
||||||
|
j.state = 'START_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000003:
|
||||||
|
j.state = 'STOP_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000001:
|
||||||
|
j.state = 'STOPPED';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
|
||||||
|
j.controlsAccepted = [];
|
||||||
|
if ((controlsAccepted & 0x00000010) == 0x00000010)
|
||||||
|
{
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDDISABLE');
|
||||||
|
}
|
||||||
|
if ((controlsAccepted & 0x00000008) == 0x00000008) { j.controlsAccepted.push('SERVICE_CONTROL_PARAMCHANGE'); }
|
||||||
|
if ((controlsAccepted & 0x00000002) == 0x00000002) { j.controlsAccepted.push('SERVICE_CONTROL_PAUSE'); j.controlsAccepted.push('SERVICE_CONTROL_CONTINUE'); }
|
||||||
|
if ((controlsAccepted & 0x00000100) == 0x00000100) { j.controlsAccepted.push('SERVICE_CONTROL_PRESHUTDOWN'); }
|
||||||
|
if ((controlsAccepted & 0x00000004) == 0x00000004) { j.controlsAccepted.push('SERVICE_CONTROL_SHUTDOWN'); }
|
||||||
|
if ((controlsAccepted & 0x00000001) == 0x00000001) { j.controlsAccepted.push('SERVICE_CONTROL_STOP'); }
|
||||||
|
if ((controlsAccepted & 0x00000020) == 0x00000020) { j.controlsAccepted.push('SERVICE_CONTROL_HARDWAREPROFILECHANGE'); }
|
||||||
|
if ((controlsAccepted & 0x00000040) == 0x00000040) { j.controlsAccepted.push('SERVICE_CONTROL_POWEREVENT'); }
|
||||||
|
if ((controlsAccepted & 0x00000080) == 0x00000080) { j.controlsAccepted.push('SERVICE_CONTROL_SESSIONCHANGE'); }
|
||||||
|
j.pid = token.Deref((7 * 4), 4).toBuffer().readUInt32LE();
|
||||||
|
return (j);
|
||||||
|
}
|
||||||
|
|
||||||
|
function serviceManager()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'service-manager';
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this.GM = require('_GenericMarshal');
|
||||||
|
this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this.proxy.CreateMethod('OpenSCManagerA');
|
||||||
|
this.proxy.CreateMethod('EnumServicesStatusExA');
|
||||||
|
this.proxy.CreateMethod('OpenServiceA');
|
||||||
|
this.proxy.CreateMethod('QueryServiceStatusEx');
|
||||||
|
this.proxy.CreateMethod('ControlService');
|
||||||
|
this.proxy.CreateMethod('StartServiceA');
|
||||||
|
this.proxy.CreateMethod('CloseServiceHandle');
|
||||||
|
this.proxy.CreateMethod('CreateServiceA');
|
||||||
|
this.proxy.CreateMethod('ChangeServiceConfig2A');
|
||||||
|
this.proxy.CreateMethod('DeleteService');
|
||||||
|
this.proxy.CreateMethod('AllocateAndInitializeSid');
|
||||||
|
this.proxy.CreateMethod('CheckTokenMembership');
|
||||||
|
this.proxy.CreateMethod('FreeSid');
|
||||||
|
|
||||||
|
this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this.proxy2.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
this.isAdmin = function isAdmin() {
|
||||||
|
var NTAuthority = this.GM.CreateVariable(6);
|
||||||
|
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||||
|
var AdministratorsGroup = this.GM.CreatePointer();
|
||||||
|
var admin = false;
|
||||||
|
|
||||||
|
if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||||
|
{
|
||||||
|
var member = this.GM.CreateInteger();
|
||||||
|
if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||||
|
{
|
||||||
|
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||||
|
}
|
||||||
|
this.proxy.FreeSid(AdministratorsGroup.Deref());
|
||||||
|
}
|
||||||
|
return admin;
|
||||||
|
};
|
||||||
|
this.getProgramFolder = function getProgramFolder()
|
||||||
|
{
|
||||||
|
if (require('os').arch() == 'x64')
|
||||||
|
{
|
||||||
|
// 64 bit Windows
|
||||||
|
if (this.GM.PointerSize == 4)
|
||||||
|
{
|
||||||
|
return process.env['ProgramFiles(x86)']; // 32 Bit App
|
||||||
|
}
|
||||||
|
return process.env['ProgramFiles']; // 64 bit App
|
||||||
|
}
|
||||||
|
|
||||||
|
// 32 bit Windows
|
||||||
|
return process.env['ProgramFiles'];
|
||||||
|
};
|
||||||
|
this.getServiceFolder = function getServiceFolder() { return this.getProgramFolder() + '\\mesh'; };
|
||||||
|
|
||||||
|
this.enumerateService = function () {
|
||||||
|
var machineName = this.GM.CreatePointer();
|
||||||
|
var dbName = this.GM.CreatePointer();
|
||||||
|
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004);
|
||||||
|
|
||||||
|
var bytesNeeded = this.GM.CreatePointer();
|
||||||
|
var servicesReturned = this.GM.CreatePointer();
|
||||||
|
var resumeHandle = this.GM.CreatePointer();
|
||||||
|
//var services = this.proxy.CreateVariable(262144);
|
||||||
|
var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||||
|
if (bytesNeeded.IntVal <= 0) {
|
||||||
|
throw ('error enumerating services');
|
||||||
|
}
|
||||||
|
var sz = bytesNeeded.IntVal;
|
||||||
|
var services = this.GM.CreateVariable(sz);
|
||||||
|
this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||||
|
console.log("servicesReturned", servicesReturned.IntVal);
|
||||||
|
|
||||||
|
var ptrSize = dbName._size;
|
||||||
|
var blockSize = 36 + (2 * ptrSize);
|
||||||
|
blockSize += ((ptrSize - (blockSize % ptrSize)) % ptrSize);
|
||||||
|
var retVal = [];
|
||||||
|
for (var i = 0; i < servicesReturned.IntVal; ++i) {
|
||||||
|
var token = services.Deref(i * blockSize, blockSize);
|
||||||
|
var j = {};
|
||||||
|
j.name = token.Deref(0, ptrSize).Deref().String;
|
||||||
|
j.displayName = token.Deref(ptrSize, ptrSize).Deref().String;
|
||||||
|
j.status = parseServiceStatus(token.Deref(2 * ptrSize, 36));
|
||||||
|
retVal.push(j);
|
||||||
|
}
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
this.getService = function (name) {
|
||||||
|
var serviceName = this.GM.CreateVariable(name);
|
||||||
|
var ptr = this.GM.CreatePointer();
|
||||||
|
var bytesNeeded = this.GM.CreateVariable(ptr._size);
|
||||||
|
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
|
||||||
|
if (handle.Val == 0) { throw ('could not open ServiceManager'); }
|
||||||
|
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
|
||||||
|
if (h.Val != 0) {
|
||||||
|
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
|
||||||
|
var status = this.GM.CreateVariable(bytesNeeded.toBuffer().readUInt32LE());
|
||||||
|
success = this.proxy.QueryServiceStatusEx(h, 0, status, status._size, bytesNeeded);
|
||||||
|
if (success != 0) {
|
||||||
|
retVal = {};
|
||||||
|
retVal.status = parseServiceStatus(status);
|
||||||
|
retVal._scm = handle;
|
||||||
|
retVal._service = h;
|
||||||
|
retVal._GM = this.GM;
|
||||||
|
retVal._proxy = this.proxy;
|
||||||
|
require('events').inherits(retVal);
|
||||||
|
retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); });
|
||||||
|
retVal.name = name;
|
||||||
|
retVal.stop = function () {
|
||||||
|
if (this.status.state == 'RUNNING') {
|
||||||
|
var newstate = this._GM.CreateVariable(36);
|
||||||
|
var success = this._proxy.ControlService(this._service, 0x00000001, newstate);
|
||||||
|
if (success == 0) {
|
||||||
|
throw (this.name + '.stop() failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retVal.start = function () {
|
||||||
|
if (this.status.state == 'STOPPED') {
|
||||||
|
var success = this._proxy.StartServiceA(this._service, 0, 0);
|
||||||
|
if (success == 0) {
|
||||||
|
throw (this.name + '.start() failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
throw ('could not find service: ' + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.isAdmin = function isAdmin()
|
||||||
|
{
|
||||||
|
return (require('user-sessions').isRoot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.installService = function installService(options)
|
||||||
|
{
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
|
||||||
|
|
||||||
|
// Before we start, we need to copy the binary to the right place
|
||||||
|
var folder = this.getServiceFolder();
|
||||||
|
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
|
||||||
|
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
|
||||||
|
options.servicePath = folder + '\\' + options.name + '.exe';
|
||||||
|
|
||||||
|
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
|
||||||
|
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
|
||||||
|
if (handle.Val == 0) { throw ('error opening SCManager'); }
|
||||||
|
var serviceName = this.GM.CreateVariable(options.name);
|
||||||
|
var displayName = this.GM.CreateVariable(options.name);
|
||||||
|
var allAccess = 0x000F01FF;
|
||||||
|
var serviceType;
|
||||||
|
|
||||||
|
|
||||||
|
switch (options.startType) {
|
||||||
|
case 'BOOT_START':
|
||||||
|
serviceType = 0x00;
|
||||||
|
break;
|
||||||
|
case 'SYSTEM_START':
|
||||||
|
serviceType = 0x01;
|
||||||
|
break;
|
||||||
|
case 'AUTO_START':
|
||||||
|
serviceType = 0x02;
|
||||||
|
break;
|
||||||
|
case 'DEMAND_START':
|
||||||
|
serviceType = 0x03;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
serviceType = 0x04; // Disabled
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var h = this.proxy.CreateServiceA(handle, serviceName, displayName, allAccess, 0x10 | 0x100, serviceType, 0, servicePath, 0, 0, 0, 0, 0);
|
||||||
|
if (h.Val == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service: ' + this.proxy2.GetLastError().Val); }
|
||||||
|
if (options.description) {
|
||||||
|
console.log(options.description);
|
||||||
|
|
||||||
|
var dscPtr = this.GM.CreatePointer();
|
||||||
|
dscPtr.Val = this.GM.CreateVariable(options.description);
|
||||||
|
|
||||||
|
if (this.proxy.ChangeServiceConfig2A(h, 1, dscPtr) == 0) {
|
||||||
|
this.proxy.CloseServiceHandle(h);
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
throw ('Unable to set description');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.proxy.CloseServiceHandle(h);
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
return (this.getService(options.name));
|
||||||
|
}
|
||||||
|
if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||||
|
|
||||||
|
switch (this.getServiceType())
|
||||||
|
{
|
||||||
|
case 'init':
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
|
||||||
|
console.log('copying ' + options.servicePath);
|
||||||
|
var m = require('fs').statSync('/etc/init.d/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/etc/init.d/' + options.name, m);
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update._moduleName = options.name;
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('update-rc.d ' + options.name + ' defaults\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
//update-rc.d meshagent defaults # creates symlinks for rc.d
|
||||||
|
//service meshagent start
|
||||||
|
|
||||||
|
this._update.waitExit();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'systemd':
|
||||||
|
var serviceDescription = options.description ? options.description : 'MeshCentral Agent';
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh')) { require('fs').mkdirSync('/usr/local/mesh'); }
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh/' + options.name);
|
||||||
|
var m = require('fs').statSync('/usr/local/mesh/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/usr/local/mesh/' + options.name, m);
|
||||||
|
require('fs').writeFileSync('/lib/systemd/system/' + options.name + '.service', '[Unit]\nDescription=' + serviceDescription + '\n[Service]\nExecStart=/usr/local/mesh/' + options.name + '\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=' + options.name + '.service\n', { flags: 'w' });
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update._moduleName = options.name;
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('systemctl enable ' + options.name + '.service\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
this._update.waitExit();
|
||||||
|
break;
|
||||||
|
default: // unknown platform service type
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||||
|
|
||||||
|
// Mac OS
|
||||||
|
var stdoutpath = (options.stdout ? ('<key>StandardOutPath</key>\n<string>' + options.stdout + '</string>') : '');
|
||||||
|
var autoStart = (options.startType == 'AUTO_START' ? '<true/>' : '<false/>');
|
||||||
|
var params = ' <key>ProgramArguments</key>\n';
|
||||||
|
params += ' <array>\n';
|
||||||
|
params += (' <string>/usr/local/mesh_services/' + options.name + '/' + options.name + '</string>\n');
|
||||||
|
if(options.parameters)
|
||||||
|
{
|
||||||
|
for(var itm in options.parameters)
|
||||||
|
{
|
||||||
|
params += (' <string>' + options.parameters[itm] + '</string>\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params += ' </array>\n';
|
||||||
|
|
||||||
|
var plist = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||||
|
plist += '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
|
||||||
|
plist += '<plist version="1.0">\n';
|
||||||
|
plist += ' <dict>\n';
|
||||||
|
plist += ' <key>Label</key>\n';
|
||||||
|
plist += (' <string>' + options.name + '</string>\n');
|
||||||
|
plist += (params + '\n');
|
||||||
|
plist += ' <key>WorkingDirectory</key>\n';
|
||||||
|
plist += (' <string>/usr/local/mesh_services/' + options.name + '</string>\n');
|
||||||
|
plist += (stdoutpath + '\n');
|
||||||
|
plist += ' <key>RunAtLoad</key>\n';
|
||||||
|
plist += (autoStart + '\n');
|
||||||
|
plist += ' </dict>\n';
|
||||||
|
plist += '</plist>';
|
||||||
|
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_services')) { require('fs').mkdirSync('/usr/local/mesh_services'); }
|
||||||
|
if (!require('fs').existsSync('/Library/LaunchDaemons/' + options.name + '.plist'))
|
||||||
|
{
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_services/' + options.name)) { require('fs').mkdirSync('/usr/local/mesh_services/' + options.name); }
|
||||||
|
if (options.binary)
|
||||||
|
{
|
||||||
|
require('fs').writeFileSync('/usr/local/mesh_services/' + options.name + '/' + options.name, options.binary);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh_services/' + options.name + '/' + options.name);
|
||||||
|
}
|
||||||
|
require('fs').writeFileSync('/Library/LaunchDaemons/' + options.name + '.plist', plist);
|
||||||
|
var m = require('fs').statSync('/usr/local/mesh_services/' + options.name + '/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/usr/local/mesh_services/' + options.name + '/' + options.name, m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Service: ' + options.name + ' already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.uninstallService = function uninstallService(name)
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||||
|
|
||||||
|
if (typeof (name) == 'object') { name = name.name; }
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
var service = this.getService(name);
|
||||||
|
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
||||||
|
{
|
||||||
|
if (this.proxy.DeleteService(service._service) == 0)
|
||||||
|
{
|
||||||
|
throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
switch (this.getServiceType())
|
||||||
|
{
|
||||||
|
case 'init':
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('service ' + name + ' stop\n');
|
||||||
|
this._update.stdin.write('update-rc.d -f ' + name + ' remove\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
this._update.waitExit();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/etc/init.d/' + name);
|
||||||
|
console.log(name + ' uninstalled');
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(name + ' could not be uninstalled', e)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'systemd':
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('systemctl stop ' + name + '.service\n');
|
||||||
|
this._update.stdin.write('systemctl disable ' + name + '.service\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
this._update.waitExit();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/usr/local/mesh/' + name);
|
||||||
|
require('fs').unlinkSync('/lib/systemd/system/' + name + '.service');
|
||||||
|
console.log(name + ' uninstalled');
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(name + ' could not be uninstalled', e)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // unknown platform service type
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
if (require('fs').existsSync('/Library/LaunchDaemons/' + name + '.plist'))
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.on('data', function (chunk) { });
|
||||||
|
child.stdin.write('launchctl stop ' + name + '\n');
|
||||||
|
child.stdin.write('launchctl unload /Library/LaunchDaemons/' + name + '.plist\n');
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/usr/local/mesh_services/' + name + '/' + name);
|
||||||
|
require('fs').unlinkSync('/Library/LaunchDaemons/' + name + '.plist');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
throw ('Error uninstalling service: ' + name + ' => ' + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').rmdirSync('/usr/local/mesh_services/' + name);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Service: ' + name + ' does not exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
this.getServiceType = function getServiceType()
|
||||||
|
{
|
||||||
|
return (require('process-manager').getProcessInfo(1).Name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = serviceManager;
|
343
agents-new/modules_meshcmd/smbios.js
Normal file
343
agents-new/modules_meshcmd/smbios.js
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
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) { }
|
||||||
|
try { Object.defineProperty(String.prototype, "replaceAll", { value: function replaceAll(oldVal, newVal) { return (this.split(oldVal).join(newVal)); } }); } catch (e) { }
|
||||||
|
|
||||||
|
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'];
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
this._native = this._marshal.CreateNativeProxy("Kernel32.dll");
|
||||||
|
|
||||||
|
this._native.CreateMethod('EnumSystemFirmwareTables');
|
||||||
|
this._native.CreateMethod('GetSystemFirmwareTable');
|
||||||
|
}
|
||||||
|
if (process.platform == 'linux') {
|
||||||
|
this._canonicalizeData = function _canonicalizeData(data) {
|
||||||
|
var lines = data.toString().split('Header and Data:\x0A');
|
||||||
|
var MemoryStream = require('MemoryStream');
|
||||||
|
var ms = new MemoryStream();
|
||||||
|
|
||||||
|
for (var i = 1; i < lines.length; ++i) {
|
||||||
|
var tokens = lines[i].split('Strings:\x0A');
|
||||||
|
var header = tokens[0].split('\x0A\x0A')[0].replaceAll('\x0A', '').trim().replaceAll(' ', '').replaceAll('\x09', '');
|
||||||
|
ms.write(Buffer.from(header, 'hex'));
|
||||||
|
if (tokens.length > 1) {
|
||||||
|
var strings = tokens[1].split('\x0A\x0A')[0].split('\x0A');
|
||||||
|
var stringsFinal = [];
|
||||||
|
for (var strx in strings) {
|
||||||
|
var tmp = strings[strx].trim().replaceAll(' ', '').replaceAll('\x09', '');
|
||||||
|
if (!(tmp[0] == '"')) { stringsFinal.push(tmp); }
|
||||||
|
}
|
||||||
|
ms.write(Buffer.from(stringsFinal.join(''), 'hex'));
|
||||||
|
ms.write(Buffer.from('00', 'hex'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ms.write(Buffer.from('0000', 'hex'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var retVal = ms.buffer;
|
||||||
|
retVal.ms = ms;
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this._parse = function _parse(SMData) {
|
||||||
|
var ret = {};
|
||||||
|
var pbyte;
|
||||||
|
var i = 0
|
||||||
|
var SMData;
|
||||||
|
var structcount = 0;
|
||||||
|
|
||||||
|
while (SMData && i < SMData.length)
|
||||||
|
{
|
||||||
|
var SMtype = SMData[i];
|
||||||
|
var SMlength = SMData[i + 1];
|
||||||
|
|
||||||
|
if (!ret[SMtype]) { ret[SMtype] = []; }
|
||||||
|
ret[SMtype].push(SMData.slice(i + 4, i + SMlength));
|
||||||
|
if (process.platform == 'win32') { ret[SMtype].peek()._ext = pbyte; }
|
||||||
|
i += SMlength;
|
||||||
|
|
||||||
|
ret[SMtype].peek()._strings = [];
|
||||||
|
|
||||||
|
while (SMData[i] != 0 && i <= SMData.length)
|
||||||
|
{
|
||||||
|
var strstart = i;
|
||||||
|
|
||||||
|
// Start of String, find end of string
|
||||||
|
while (SMData[i++] != 0 && i <= SMData.length);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ret[SMtype].peek()._strings.push(SMData.slice(strstart, i).toString().trim());
|
||||||
|
}
|
||||||
|
catch (ee)
|
||||||
|
{
|
||||||
|
console.log('oops');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += (ret[SMtype].peek()._strings.length == 0) ? 2 : 1;
|
||||||
|
++structcount;
|
||||||
|
//console.log('End of Table[' + SMtype + ']: ' + i);
|
||||||
|
}
|
||||||
|
//console.log('Struct Count = ' + structcount);
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
this.get = function get(callback) {
|
||||||
|
if (process.platform == 'win32') {
|
||||||
|
var size = this._native.GetSystemFirmwareTable(RSMB, 0, 0, 0).Val;
|
||||||
|
//console.log('Table Size: ' + size);
|
||||||
|
|
||||||
|
var PtrSize = this._marshal.CreatePointer()._size;
|
||||||
|
var buffer = this._marshal.CreateVariable(size);
|
||||||
|
var written = this._native.GetSystemFirmwareTable(RSMB, 0, buffer, size).Val;
|
||||||
|
//console.log('Written Size: ' + written);
|
||||||
|
|
||||||
|
var rawBuffer = buffer.toBuffer();
|
||||||
|
var length = buffer.Deref(4, 4).toBuffer().readUInt32LE(0);
|
||||||
|
|
||||||
|
pbyte = buffer.Deref(8, length);
|
||||||
|
SMData = pbyte.toBuffer();
|
||||||
|
|
||||||
|
if (callback) { callback.apply(this, [this._parse(SMData)]); return; } else { return (this._parse(SMData)); }
|
||||||
|
}
|
||||||
|
if (process.platform == 'linux') {
|
||||||
|
var MemoryStream = require('MemoryStream');
|
||||||
|
this.child = require('child_process').execFile('/usr/sbin/dmidecode', ['dmidecode', '-u']);
|
||||||
|
this.child.SMBiosTable = this;
|
||||||
|
this.child.ms = new MemoryStream();
|
||||||
|
this.child.ms.callback = callback;
|
||||||
|
this.child.ms.child = this.child;
|
||||||
|
this.child.stdout.on('data', function (buffer) { this.parent.ms.write(buffer); });
|
||||||
|
this.child.on('exit', function () { this.ms.end(); });
|
||||||
|
this.child.ms.on('end', function () {
|
||||||
|
//console.log('read ' + this.buffer.length + ' bytes');
|
||||||
|
if (this.buffer.length < 300) {
|
||||||
|
//console.log('Not enough permission to read SMBiosTable');
|
||||||
|
if (this.callback) { this.callback.apply(this.child.SMBiosTable, []); }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var SMData = this.child.SMBiosTable._canonicalizeData(this.buffer);
|
||||||
|
var j = this.child.SMBiosTable._parse(SMData);
|
||||||
|
if (this.callback) { this.callback.apply(this.child.SMBiosTable, [j]); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (callback) { callback.apply(this, [null]); return; } else { return (null); }
|
||||||
|
};
|
||||||
|
this.parse = function parse(data) {
|
||||||
|
var r = {};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.processorInfo = this.processorInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.memoryInfo = this.memoryInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.systemInfo = this.systemInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.systemSlots = this.systemInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.amtInfo = this.amtInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
this.processorInfo = function processorInfo(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var ret = [];
|
||||||
|
var ptype = ['ERROR', 'Other', 'Unknown', 'CPU', 'ALU', 'DSP', 'GPU'];
|
||||||
|
var statusString = ['Unknown', 'Enabled', 'Disabled by user', 'Disabled by BIOS', 'Idle', 'Reserved', 'Reserved', 'Other'];
|
||||||
|
var cpuid = 0;
|
||||||
|
while (data[4] && data[4].length > 0) {
|
||||||
|
var p = data[4].pop();
|
||||||
|
var populated = p[20] & 0x40;
|
||||||
|
var status = p[20] & 0x07
|
||||||
|
if (populated) {
|
||||||
|
var j = { _ObjectID: 'SMBiosTables.processorInfo' };
|
||||||
|
j.Processor = ptype[p[1]];
|
||||||
|
j.MaxSpeed = p.readUInt16LE(16) + ' Mhz';
|
||||||
|
if (p[31]) { j.Cores = p[31]; }
|
||||||
|
if (p[33]) { j.Threads = p[33]; }
|
||||||
|
j.Populated = 1;
|
||||||
|
j.Status = statusString[status];
|
||||||
|
j.Socket = p._strings[p[0] - 1];
|
||||||
|
j.Manufacturer = p._strings[p[3] - 1];
|
||||||
|
j.Version = p._strings[p[12] - 1];
|
||||||
|
ret.push(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
this.memoryInfo = function memoryInfo(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = { _ObjectID: 'SMBiosTables.memoryInfo' };
|
||||||
|
if (data[16]) {
|
||||||
|
var m = data[16].peek();
|
||||||
|
retVal.location = memoryLocation[m[0]];
|
||||||
|
if ((retVal.maxCapacityKb = m.readUInt32LE(3)) == 0x80000000) {
|
||||||
|
retVal.maxCapacityKb = 'A really big number';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.systemInfo = function systemInfo(data)
|
||||||
|
{
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = { _ObjectID: 'SMBiosTables.systemInfo' };
|
||||||
|
if (data[1])
|
||||||
|
{
|
||||||
|
var si = data[1].peek();
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
this.systemSlots = function systemSlots(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = [];
|
||||||
|
if (data[9]) {
|
||||||
|
while (data[9].length > 0) {
|
||||||
|
var ss = data[9].pop();
|
||||||
|
retVal.push({ name: ss._strings[ss[0] - 1] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.amtInfo = function amtInfo(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = { AMT: false };
|
||||||
|
if (data[130] && data[130].peek().slice(0, 4).toString() == '$AMT') {
|
||||||
|
var amt = data[130].peek();
|
||||||
|
retVal.AMT = amt[4] ? true : false;
|
||||||
|
if (retVal.AMT) {
|
||||||
|
retVal.enabled = amt[5] ? true : false;
|
||||||
|
retVal.storageRedirection = amt[6] ? true : false;
|
||||||
|
retVal.serialOverLan = amt[7] ? true : false;
|
||||||
|
retVal.kvm = amt[14] ? true : false;
|
||||||
|
if (data[131].peek() && data[131].peek().slice(52, 56).toString() == 'vPro') {
|
||||||
|
var settings = data[131].peek();
|
||||||
|
if (settings[0] & 0x04) { retVal.TXT = (settings[0] & 0x08) ? true : false; }
|
||||||
|
if (settings[0] & 0x10) { retVal.VMX = (settings[0] & 0x20) ? true : false; }
|
||||||
|
retVal.MEBX = settings.readUInt16LE(10).toString() + '.' + settings.readUInt16LE(8).toString() + '.' + settings.readUInt16LE(6).toString() + '.' + settings.readUInt16LE(4).toString();
|
||||||
|
|
||||||
|
var mecap = settings.slice(20, 32);
|
||||||
|
retVal.ManagementEngine = mecap.readUInt16LE(6).toString() + '.' + mecap.readUInt16LE(4).toString() + '.' + mecap.readUInt16LE(2).toString() + '.' + mecap.readUInt16LE(0).toString();
|
||||||
|
|
||||||
|
//var lan = settings.slice(36, 48);
|
||||||
|
//console.log(lan.toString('hex'));
|
||||||
|
//retVal.LAN = (lan.readUInt16LE(10) & 0x03).toString() + '/' + ((lan.readUInt16LE(10) & 0xF8) >> 3).toString();
|
||||||
|
|
||||||
|
//console.log(lan.readUInt16LE(3));
|
||||||
|
//retVal.WLAN = (lan.readUInt16LE(3) & 0x07).toString() + '/' + ((lan.readUInt16LE(3) & 0xF8) >> 3).toString() + '/' + (lan.readUInt16LE(3) >> 8).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.smTableTypes = {
|
||||||
|
0: 'BIOS information',
|
||||||
|
1: 'System information',
|
||||||
|
2: 'Baseboard (or Module) information',
|
||||||
|
4: 'Processor information',
|
||||||
|
5: 'memory controller information',
|
||||||
|
6: 'Memory module information',
|
||||||
|
7: 'Cache information',
|
||||||
|
8: 'Port connector information',
|
||||||
|
9: 'System slots',
|
||||||
|
10: 'On board devices information',
|
||||||
|
11: 'OEM strings',
|
||||||
|
12: 'System configuration options',
|
||||||
|
13: 'BIOS language information',
|
||||||
|
14: 'Group associations',
|
||||||
|
15: 'System event log',
|
||||||
|
16: 'Physical memory array',
|
||||||
|
17: 'Memory device',
|
||||||
|
18: '32bit memory error information',
|
||||||
|
19: 'Memory array mapped address',
|
||||||
|
20: 'Memory device mapped address',
|
||||||
|
21: 'Built-in pointing device',
|
||||||
|
22: 'Portable battery',
|
||||||
|
23: 'System reset',
|
||||||
|
24: 'Hardware security',
|
||||||
|
25: 'System power controls',
|
||||||
|
26: 'Voltage probe',
|
||||||
|
27: 'Cooling device',
|
||||||
|
28: 'Temperature probe',
|
||||||
|
29: 'Electrical current probe',
|
||||||
|
30: 'Out-of-band remote access',
|
||||||
|
31: 'Boot integrity services (BIS) entry point',
|
||||||
|
32: 'System boot information',
|
||||||
|
33: '64bit memory error information',
|
||||||
|
34: 'Management device',
|
||||||
|
35: 'Management device component',
|
||||||
|
36: 'Management device threshold data',
|
||||||
|
37: 'Memory channel',
|
||||||
|
38: 'IPMI device information',
|
||||||
|
39: 'System power supply',
|
||||||
|
40: 'Additional information',
|
||||||
|
41: 'Onboard devices extended information',
|
||||||
|
42: 'Management controller host interface',
|
||||||
|
126: 'Inactive',
|
||||||
|
127: 'End-of-table'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new SMBiosTables();
|
750
agents-new/modules_meshcmd/user-sessions.js
Normal file
750
agents-new/modules_meshcmd/user-sessions.js
Normal file
@ -0,0 +1,750 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var 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);
|
||||||
|
var WTS_REMOTE_DISCONNECT = (0x4);
|
||||||
|
var WTS_SESSION_LOGON = (0x5);
|
||||||
|
var WTS_SESSION_LOGOFF = (0x6);
|
||||||
|
var WTS_SESSION_LOCK = (0x7);
|
||||||
|
var WTS_SESSION_UNLOCK = (0x8);
|
||||||
|
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';
|
||||||
|
require('events').EventEmitter.call(this, true)
|
||||||
|
.createEvent('changed')
|
||||||
|
.createEvent('locked')
|
||||||
|
.createEvent('unlocked');
|
||||||
|
|
||||||
|
this.enumerateUsers = function enumerateUsers()
|
||||||
|
{
|
||||||
|
var promise = require('promise');
|
||||||
|
var p = new promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__resolver = res;
|
||||||
|
this.__rejector = rej;
|
||||||
|
});
|
||||||
|
p.__handler = function __handler(users)
|
||||||
|
{
|
||||||
|
p.__resolver(users);
|
||||||
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.Current(p.__handler);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
p.__rejector(e);
|
||||||
|
}
|
||||||
|
p.parent = this;
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this._serviceHooked = false;
|
||||||
|
this._marshal = require('_GenericMarshal');
|
||||||
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||||
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||||
|
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||||
|
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||||
|
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||||
|
this._wts.CreateMethod('WTSFreeMemory');
|
||||||
|
}
|
||||||
|
catch(exc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
this._advapi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this._advapi.CreateMethod('AllocateAndInitializeSid');
|
||||||
|
this._advapi.CreateMethod('CheckTokenMembership');
|
||||||
|
this._advapi.CreateMethod('FreeSid');
|
||||||
|
|
||||||
|
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
||||||
|
this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1});
|
||||||
|
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 =
|
||||||
|
{
|
||||||
|
'WTSInitialProgram': 0,
|
||||||
|
'WTSApplicationName': 1,
|
||||||
|
'WTSWorkingDirectory': 2,
|
||||||
|
'WTSOEMId': 3,
|
||||||
|
'WTSSessionId': 4,
|
||||||
|
'WTSUserName': 5,
|
||||||
|
'WTSWinStationName': 6,
|
||||||
|
'WTSDomainName': 7,
|
||||||
|
'WTSConnectState': 8,
|
||||||
|
'WTSClientBuildNumber': 9,
|
||||||
|
'WTSClientName': 10,
|
||||||
|
'WTSClientDirectory': 11,
|
||||||
|
'WTSClientProductId': 12,
|
||||||
|
'WTSClientHardwareId': 13,
|
||||||
|
'WTSClientAddress': 14,
|
||||||
|
'WTSClientDisplay': 15,
|
||||||
|
'WTSClientProtocolType': 16,
|
||||||
|
'WTSIdleTime': 17,
|
||||||
|
'WTSLogonTime': 18,
|
||||||
|
'WTSIncomingBytes': 19,
|
||||||
|
'WTSOutgoingBytes': 20,
|
||||||
|
'WTSIncomingFrames': 21,
|
||||||
|
'WTSOutgoingFrames': 22,
|
||||||
|
'WTSClientInfo': 23,
|
||||||
|
'WTSSessionInfo': 24,
|
||||||
|
'WTSSessionInfoEx': 25,
|
||||||
|
'WTSConfigInfo': 26,
|
||||||
|
'WTSValidationInfo': 27,
|
||||||
|
'WTSSessionAddressV4': 28,
|
||||||
|
'WTSIsRemoteSession': 29
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isRoot = function isRoot()
|
||||||
|
{
|
||||||
|
var NTAuthority = this._marshal.CreateVariable(6);
|
||||||
|
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||||
|
|
||||||
|
var AdministratorsGroup = this._marshal.CreatePointer();
|
||||||
|
var admin = false;
|
||||||
|
|
||||||
|
if (this._advapi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||||
|
{
|
||||||
|
var member = this._marshal.CreateInteger();
|
||||||
|
if (this._advapi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||||
|
{
|
||||||
|
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||||
|
}
|
||||||
|
this._advapi.FreeSid(AdministratorsGroup.Deref());
|
||||||
|
}
|
||||||
|
return admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
|
||||||
|
{
|
||||||
|
var buffer = this._marshal.CreatePointer();
|
||||||
|
var bytesReturned = this._marshal.CreateVariable(4);
|
||||||
|
|
||||||
|
if (this._wts.WTSQuerySessionInformationA(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSQuerySessionInformation: ' + this._kernel32.GetLastError.Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
var retVal = buffer.Deref().String;
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(buffer.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Current = function Current(cb)
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
var pinfo = this._marshal.CreatePointer();
|
||||||
|
var count = this._marshal.CreateVariable(4);
|
||||||
|
if (this._wts.WTSEnumerateSessionsA(0, 0, 1, pinfo, count).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSEnumerateSessionsA: ' + this._kernel32.GetLastError().Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count.toBuffer().readUInt32LE() ; ++i)
|
||||||
|
{
|
||||||
|
var info = pinfo.Deref().Deref(i * (this._marshal.PointerSize == 4 ? 12 : 24), this._marshal.PointerSize == 4 ? 12 : 24);
|
||||||
|
var j = { SessionId: info.toBuffer().readUInt32LE() };
|
||||||
|
j.StationName = info.Deref(this._marshal.PointerSize == 4 ? 4 : 8, this._marshal.PointerSize).Deref().String;
|
||||||
|
j.State = this.SessionStates[info.Deref(this._marshal.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE()];
|
||||||
|
if (j.State == 'Active') {
|
||||||
|
j.Username = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSUserName);
|
||||||
|
j.Domain = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSDomainName);
|
||||||
|
}
|
||||||
|
retVal[j.SessionId] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||||
|
|
||||||
|
Object.defineProperty(retVal, 'Active', { value: showActiveOnly(retVal) });
|
||||||
|
if (cb) { cb(retVal); }
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
|
||||||
|
// from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
|
||||||
|
// on a semaphore for us to return. If we call now, we may deadlock on Windows 7, becuase it will try to notify immediately
|
||||||
|
this.immediate = setImmediate(function (self)
|
||||||
|
{
|
||||||
|
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||||
|
if (self.parent._wts) { 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)
|
||||||
|
{
|
||||||
|
switch(msg.message)
|
||||||
|
{
|
||||||
|
case WM_WTSSESSION_CHANGE:
|
||||||
|
switch(msg.wparam)
|
||||||
|
{
|
||||||
|
case WTS_SESSION_LOCK:
|
||||||
|
this.parent.enumerateUsers().then(function (users)
|
||||||
|
{
|
||||||
|
if (users[msg.lparam]) { this.parent.emit('locked', users[msg.lparam]); }
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case WTS_SESSION_UNLOCK:
|
||||||
|
this.parent.enumerateUsers().then(function (users)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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 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)
|
||||||
|
{
|
||||||
|
this.user_session.emit('changed');
|
||||||
|
});
|
||||||
|
this._users = function _users()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[0]] = tokens[1]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
this._uids = function _uids() {
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines) {
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
this.Self = function Self()
|
||||||
|
{
|
||||||
|
var promise = require('promise');
|
||||||
|
var p = new promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__resolver = res; this.__rejector = rej;
|
||||||
|
this.__child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||||
|
this.__child.promise = this;
|
||||||
|
this.__child.stdout._txt = '';
|
||||||
|
this.__child.stdout.on('data', function (chunk) { this._txt += chunk.toString(); });
|
||||||
|
this.__child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parseInt(this.stdout._txt);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
this.promise.__rejector('invalid uid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = parseInt(this.stdout._txt);
|
||||||
|
this.promise.__resolver(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return (p);
|
||||||
|
};
|
||||||
|
this.Current = function Current(cb)
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
retVal._ObjectID = 'UserSession'
|
||||||
|
Object.defineProperty(retVal, '_callback', { value: cb });
|
||||||
|
Object.defineProperty(retVal, '_child', { value: require('child_process').execFile('/usr/bin/last', ['last', '-f', '/var/run/utmp']) });
|
||||||
|
|
||||||
|
retVal._child.Parent = retVal;
|
||||||
|
retVal._child._txt = '';
|
||||||
|
retVal._child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
var lines = this._txt.split('\n');
|
||||||
|
var sessions = [];
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for(var i in lines)
|
||||||
|
{
|
||||||
|
if (lines[i])
|
||||||
|
{
|
||||||
|
var tokens = getTokens(lines[i]);
|
||||||
|
var s = { Username: tokens[0], SessionId: tokens[1] }
|
||||||
|
if (tokens[3].includes('still logged in'))
|
||||||
|
{
|
||||||
|
s.State = 'Active';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.LastActive = tokens[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.push(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessions.pop();
|
||||||
|
|
||||||
|
|
||||||
|
var usernames = {};
|
||||||
|
var promises = [];
|
||||||
|
|
||||||
|
for (var i in sessions)
|
||||||
|
{
|
||||||
|
if (sessions[i].Username != 'reboot')
|
||||||
|
{
|
||||||
|
users[sessions[i].SessionId] = sessions[i];
|
||||||
|
if(usernames[sessions[i].Username] == null)
|
||||||
|
{
|
||||||
|
usernames[sessions[i].Username] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('promise');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||||
|
if (this.Parent._callback) { this.Parent._callback.call(this.Parent, users); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var promise = require('promise');
|
||||||
|
for (var n in usernames)
|
||||||
|
{
|
||||||
|
var p = new promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__username = n;
|
||||||
|
this.__resolver = res; this.__rejector = rej;
|
||||||
|
this.__child = require('child_process').execFile('/usr/bin/id', ['id', '-u', n]);
|
||||||
|
this.__child.promise = this;
|
||||||
|
this.__child.stdout._txt = '';
|
||||||
|
this.__child.stdout.on('data', function (chunk) { this._txt += chunk.toString(); });
|
||||||
|
this.__child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parseInt(this.stdout._txt);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.promise.__rejector('invalid uid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = parseInt(this.stdout._txt);
|
||||||
|
this.promise.__resolver(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
promises.push(p);
|
||||||
|
}
|
||||||
|
promise.all(promises).then(function (plist)
|
||||||
|
{
|
||||||
|
// Done
|
||||||
|
var table = {};
|
||||||
|
for(var i in plist)
|
||||||
|
{
|
||||||
|
table[plist[i].__username] = plist[i]._internal.completedArgs[0];
|
||||||
|
}
|
||||||
|
for(var i in users)
|
||||||
|
{
|
||||||
|
users[i].uid = table[users[i].Username];
|
||||||
|
}
|
||||||
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||||
|
if (retVal._callback) { retVal._callback.call(retVal, users); }
|
||||||
|
}, function (reason)
|
||||||
|
{
|
||||||
|
// Failed
|
||||||
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||||
|
if (retVal._callback) { retVal._callback.call(retVal, users); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
retVal._child.stdout.Parent = retVal._child;
|
||||||
|
retVal._child.stdout.on('data', function (chunk) { this.Parent._txt += chunk.toString(); });
|
||||||
|
|
||||||
|
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._users = function ()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[0]] = tokens[tokens.length - 1]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
|
this._uids = function () {
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[tokens.length - 1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
|
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); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(process.platform == 'linux' || process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
this._self = function _self()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.waitExit();
|
||||||
|
return (parseInt(child.stdout.str));
|
||||||
|
}
|
||||||
|
this.isRoot = function isRoot()
|
||||||
|
{
|
||||||
|
return (this._self() == 0);
|
||||||
|
}
|
||||||
|
this.consoleUid = function consoleUid()
|
||||||
|
{
|
||||||
|
var checkstr = process.platform == 'darwin' ? 'console' : ((process.env['DISPLAY'])?process.env['DISPLAY']:':0')
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('who\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i, j;
|
||||||
|
for (i in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
for (j = 1; j < tokens.length; ++j)
|
||||||
|
{
|
||||||
|
if (tokens[j].length > 0)
|
||||||
|
{
|
||||||
|
return (parseInt(this._users()[tokens[0]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ('nobody logged into console');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
function showActiveOnly(source)
|
||||||
|
{
|
||||||
|
var retVal = [];
|
||||||
|
var unique = {};
|
||||||
|
var usernames = [];
|
||||||
|
var tmp;
|
||||||
|
|
||||||
|
for (var i in source)
|
||||||
|
{
|
||||||
|
if (source[i].State == 'Active')
|
||||||
|
{
|
||||||
|
retVal.push(source[i]);
|
||||||
|
tmp = (source[i].Domain ? (source[i].Domain + '\\') : '') + source[i].Username;
|
||||||
|
if (!unique[tmp]) { unique[tmp] = tmp;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in unique)
|
||||||
|
{
|
||||||
|
usernames.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(retVal, 'usernames', { value: usernames });
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
function getTokens(str)
|
||||||
|
{
|
||||||
|
var columns = [];
|
||||||
|
var i;
|
||||||
|
|
||||||
|
columns.push(str.substring(0, (i=str.indexOf(' '))));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
var status = str.substring(i).trim();
|
||||||
|
columns.push(status);
|
||||||
|
|
||||||
|
return (columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new UserSessions();
|
163
agents-new/modules_meshcmd/x/process-manager.js
Normal file
163
agents-new/modules_meshcmd/x/process-manager.js
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
|
||||||
|
// Used on Windows and Linux to get information about running processes
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
case 'win32':
|
||||||
|
this._kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._kernel32.CreateMethod('CreateToolhelp32Snapshot');
|
||||||
|
this._kernel32.CreateMethod('Process32First');
|
||||||
|
this._kernel32.CreateMethod('Process32Next');
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
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:
|
||||||
|
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||||
|
break;
|
||||||
|
case 'win32': // Windows processes
|
||||||
|
var retVal = {};
|
||||||
|
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0);
|
||||||
|
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)] = { 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]); }
|
||||||
|
break;
|
||||||
|
case 'linux': // Linux processes
|
||||||
|
if (!this._psp) { this._psp = {}; }
|
||||||
|
var p = this._childProcess.execFile("/bin/ps", ["ps", "-uxa"], { type: this._childProcess.SpawnTypes.TERM });
|
||||||
|
this._psp[p.pid] = p;
|
||||||
|
p.Parent = this;
|
||||||
|
p.ps = '';
|
||||||
|
p.callback = callback;
|
||||||
|
p.args = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||||
|
p.on('exit', function onGetProcesses()
|
||||||
|
{
|
||||||
|
delete this.Parent._psp[this.pid];
|
||||||
|
var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
||||||
|
for (var i in lines)
|
||||||
|
{
|
||||||
|
var tokens = lines[i].split(' ');
|
||||||
|
var tokenList = [];
|
||||||
|
for(var x in tokens)
|
||||||
|
{
|
||||||
|
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
||||||
|
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]);}
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { pid: key.PID, user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.callback)
|
||||||
|
{
|
||||||
|
this.args.unshift(retVal);
|
||||||
|
this.callback.apply(this.parent, this.args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
||||||
|
break;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
throw ('getProcessInfo() not supported for ' + process.platform);
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
var status = require('fs').readFileSync('/proc/' + pid + '/status');
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
return (info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new processManager();
|
898
agents-new/modules_meshcore/amt-lme.js
Normal file
898
agents-new/modules_meshcore/amt-lme.js
Normal file
@ -0,0 +1,898 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var 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.
|
||||||
|
var xmlParser = require('amt-xml');
|
||||||
|
|
||||||
|
// Documented in: https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/HTMLDocuments/MPSDocuments/Intel%20AMT%20Port%20Forwarding%20Protocol%20Reference%20Manual.pdf
|
||||||
|
var APF_DISCONNECT = 1;
|
||||||
|
var APF_SERVICE_REQUEST = 5;
|
||||||
|
var APF_SERVICE_ACCEPT = 6;
|
||||||
|
var APF_USERAUTH_REQUEST = 50;
|
||||||
|
var APF_USERAUTH_FAILURE = 51;
|
||||||
|
var APF_USERAUTH_SUCCESS = 52;
|
||||||
|
var APF_GLOBAL_REQUEST = 80;
|
||||||
|
var APF_REQUEST_SUCCESS = 81;
|
||||||
|
var APF_REQUEST_FAILURE = 82;
|
||||||
|
var APF_CHANNEL_OPEN = 90;
|
||||||
|
var APF_CHANNEL_OPEN_CONFIRMATION = 91;
|
||||||
|
var APF_CHANNEL_OPEN_FAILURE = 92;
|
||||||
|
var APF_CHANNEL_WINDOW_ADJUST = 93;
|
||||||
|
var APF_CHANNEL_DATA = 94;
|
||||||
|
var APF_CHANNEL_CLOSE = 97;
|
||||||
|
var APF_PROTOCOLVERSION = 192;
|
||||||
|
|
||||||
|
|
||||||
|
function lme_object() {
|
||||||
|
this.ourId = ++lme_id;
|
||||||
|
this.amtId = -1;
|
||||||
|
this.LME_CHANNEL_STATUS = 'LME_CS_FREE';
|
||||||
|
this.txWindow = 0;
|
||||||
|
this.rxWindow = 0;
|
||||||
|
this.localPort = 0;
|
||||||
|
this.errorCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stream_bufferedWrite() {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
this.buffer = [];
|
||||||
|
this._readCheckImmediate = undefined;
|
||||||
|
this._ObjectID = "bufferedWriteStream";
|
||||||
|
// Writable Events
|
||||||
|
emitterUtils.createEvent('close');
|
||||||
|
emitterUtils.createEvent('drain');
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
emitterUtils.createEvent('finish');
|
||||||
|
emitterUtils.createEvent('pipe');
|
||||||
|
emitterUtils.createEvent('unpipe');
|
||||||
|
|
||||||
|
// Readable Events
|
||||||
|
emitterUtils.createEvent('readable');
|
||||||
|
this.isEmpty = function () {
|
||||||
|
return (this.buffer.length == 0);
|
||||||
|
};
|
||||||
|
this.isWaiting = function () {
|
||||||
|
return (this._readCheckImmediate == undefined);
|
||||||
|
};
|
||||||
|
this.write = function (chunk) {
|
||||||
|
for (var args in arguments) { if (typeof (arguments[args]) == 'function') { this.once('drain', arguments[args]); break; } }
|
||||||
|
var tmp = Buffer.alloc(chunk.length);
|
||||||
|
chunk.copy(tmp);
|
||||||
|
this.buffer.push({ offset: 0, data: tmp });
|
||||||
|
this.emit('readable');
|
||||||
|
return (this.buffer.length == 0 ? true : false);
|
||||||
|
};
|
||||||
|
this.read = function () {
|
||||||
|
var size = arguments.length == 0 ? undefined : arguments[0];
|
||||||
|
var bytesRead = 0;
|
||||||
|
var list = [];
|
||||||
|
while ((size == undefined || bytesRead < size) && this.buffer.length > 0) {
|
||||||
|
var len = this.buffer[0].data.length - this.buffer[0].offset;
|
||||||
|
var offset = this.buffer[0].offset;
|
||||||
|
|
||||||
|
if (len > (size - bytesRead)) {
|
||||||
|
// Only reading a subset
|
||||||
|
list.push(this.buffer[0].data.slice(offset, offset + size - bytesRead));
|
||||||
|
this.buffer[0].offset += (size - bytesRead);
|
||||||
|
bytesRead += (size - bytesRead);
|
||||||
|
} else {
|
||||||
|
// Reading the entire thing
|
||||||
|
list.push(this.buffer[0].data.slice(offset));
|
||||||
|
bytesRead += len;
|
||||||
|
this.buffer.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._readCheckImmediate = setImmediate(function (buffered) {
|
||||||
|
buffered._readCheckImmediate = undefined;
|
||||||
|
if (buffered.buffer.length == 0) {
|
||||||
|
buffered.emit('drain'); // Drained
|
||||||
|
} else {
|
||||||
|
buffered.emit('readable'); // Not drained
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
return (Buffer.concat(list));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function lme_heci(options) {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
emitterUtils.createEvent('connect');
|
||||||
|
emitterUtils.createEvent('notify');
|
||||||
|
emitterUtils.createEvent('bind');
|
||||||
|
|
||||||
|
if ((options != null) && (options.debug == true)) { lme_port_offset = -100; } // LMS debug mode
|
||||||
|
|
||||||
|
var heci = require('heci');
|
||||||
|
this.INITIAL_RXWINDOW_SIZE = 4096;
|
||||||
|
|
||||||
|
this._ObjectID = "lme";
|
||||||
|
this._LME = heci.create();
|
||||||
|
this._LME._binded = {};
|
||||||
|
this._LME.LMS = this;
|
||||||
|
this._LME.on('error', function (e) { this.LMS.emit('error', e); });
|
||||||
|
this._LME.on('connect', function () {
|
||||||
|
this.on('data', function (chunk) {
|
||||||
|
// this = HECI
|
||||||
|
var cmd = chunk.readUInt8(0);
|
||||||
|
//console.log('LME Command ' + cmd + ', ' + chunk.length + ' byte(s).');
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
default:
|
||||||
|
console.log('Unhandled LME Command ' + cmd + ', ' + chunk.length + ' byte(s).');
|
||||||
|
break;
|
||||||
|
case APF_SERVICE_REQUEST:
|
||||||
|
var nameLen = chunk.readUInt32BE(1);
|
||||||
|
var name = chunk.slice(5, nameLen + 5);
|
||||||
|
//console.log("Service Request for: " + name);
|
||||||
|
if (name == 'pfwd@amt.intel.com' || name == 'auth@amt.intel.com') {
|
||||||
|
var outBuffer = Buffer.alloc(5 + nameLen);
|
||||||
|
outBuffer.writeUInt8(6, 0);
|
||||||
|
outBuffer.writeUInt32BE(nameLen, 1);
|
||||||
|
outBuffer.write(name.toString(), 5);
|
||||||
|
this.write(outBuffer);
|
||||||
|
//console.log('Answering APF_SERVICE_REQUEST');
|
||||||
|
} else {
|
||||||
|
//console.log('UNKNOWN APF_SERVICE_REQUEST');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_GLOBAL_REQUEST:
|
||||||
|
var nameLen = chunk.readUInt32BE(1);
|
||||||
|
var name = chunk.slice(5, nameLen + 5).toString();
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case 'tcpip-forward':
|
||||||
|
var len = chunk.readUInt32BE(nameLen + 6);
|
||||||
|
var port = chunk.readUInt32BE(nameLen + 10 + len);
|
||||||
|
//console.log("[" + chunk.length + "/" + len + "] APF_GLOBAL_REQUEST for: " + name + " on port " + port);
|
||||||
|
if (this[name] == undefined) { this[name] = {}; }
|
||||||
|
if (this[name][port] != null) { // Close the existing binding
|
||||||
|
for (var i in this.sockets) {
|
||||||
|
var channel = this.sockets[i];
|
||||||
|
if (channel.localPort == port) { this.sockets[i].end(); delete this.sockets[i]; } // Close this socket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this[name][port] == null)
|
||||||
|
{ // Bind a new server socket if not already present
|
||||||
|
this[name][port] = require('net').createServer();
|
||||||
|
this[name][port].HECI = this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (lme_port_offset == 0) {
|
||||||
|
this[name][port].listen({ port: port, host: '127.0.0.1' }); // Normal mode
|
||||||
|
} else {
|
||||||
|
this[name][port].listen({ port: (port + lme_port_offset) }); // Debug mode
|
||||||
|
}
|
||||||
|
} catch (ex) { console.log('Binding error, LMS port ' + (port + lme_port_offset) + ': ' + ex) } // TODO: We can't bind
|
||||||
|
this[name][port].on('connection', function (socket) {
|
||||||
|
//console.log('New [' + socket.remoteFamily + '] TCP Connection on: ' + socket.remoteAddress + ' :' + socket.localPort);
|
||||||
|
this.HECI.LMS.bindDuplexStream(socket, socket.remoteFamily, socket.localPort - lme_port_offset);
|
||||||
|
});
|
||||||
|
this._binded[port] = true;
|
||||||
|
this.LMS.emit('bind', this._binded);
|
||||||
|
}
|
||||||
|
var outBuffer = Buffer.alloc(5);
|
||||||
|
outBuffer.writeUInt8(81, 0);
|
||||||
|
outBuffer.writeUInt32BE(port, 1);
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
case 'cancel-tcpip-forward':
|
||||||
|
var outBuffer = Buffer.alloc(1);
|
||||||
|
outBuffer.writeUInt8(APF_REQUEST_SUCCESS, 0);
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
case 'udp-send-to@amt.intel.com':
|
||||||
|
var outBuffer = Buffer.alloc(1);
|
||||||
|
outBuffer.writeUInt8(APF_REQUEST_FAILURE, 0);
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//console.log("Unknown APF_GLOBAL_REQUEST for: " + name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_OPEN_CONFIRMATION:
|
||||||
|
var rChannel = chunk.readUInt32BE(1);
|
||||||
|
var sChannel = chunk.readUInt32BE(5);
|
||||||
|
var wSize = chunk.readUInt32BE(9);
|
||||||
|
//console.log('rChannel/' + rChannel + ', sChannel/' + sChannel + ', wSize/' + wSize);
|
||||||
|
if (this.sockets[rChannel] != undefined) {
|
||||||
|
this.sockets[rChannel].lme.amtId = sChannel;
|
||||||
|
this.sockets[rChannel].lme.rxWindow = wSize;
|
||||||
|
this.sockets[rChannel].lme.txWindow = wSize;
|
||||||
|
this.sockets[rChannel].lme.LME_CHANNEL_STATUS = 'LME_CS_CONNECTED';
|
||||||
|
//console.log('LME_CS_CONNECTED');
|
||||||
|
this.sockets[rChannel].bufferedStream = new stream_bufferedWrite();
|
||||||
|
this.sockets[rChannel].bufferedStream.socket = this.sockets[rChannel];
|
||||||
|
this.sockets[rChannel].bufferedStream.on('readable', function () {
|
||||||
|
if (this.socket.lme.txWindow > 0) {
|
||||||
|
var buffer = this.read(this.socket.lme.txWindow);
|
||||||
|
var packet = Buffer.alloc(9 + buffer.length);
|
||||||
|
packet.writeUInt8(APF_CHANNEL_DATA, 0);
|
||||||
|
packet.writeUInt32BE(this.socket.lme.amtId, 1);
|
||||||
|
packet.writeUInt32BE(buffer.length, 5);
|
||||||
|
buffer.copy(packet, 9);
|
||||||
|
this.socket.lme.txWindow -= buffer.length;
|
||||||
|
this.socket.HECI.write(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].bufferedStream.on('drain', function () {
|
||||||
|
this.socket.resume();
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].on('data', function (chunk) {
|
||||||
|
if (!this.bufferedStream.write(chunk)) { this.pause(); }
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].on('end', function () {
|
||||||
|
var outBuffer = Buffer.alloc(5);
|
||||||
|
outBuffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
|
||||||
|
outBuffer.writeUInt32BE(this.lme.amtId, 1);
|
||||||
|
this.HECI.write(outBuffer);
|
||||||
|
});
|
||||||
|
this.sockets[rChannel].resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case APF_PROTOCOLVERSION:
|
||||||
|
var major = chunk.readUInt32BE(1);
|
||||||
|
var minor = chunk.readUInt32BE(5);
|
||||||
|
var reason = chunk.readUInt32BE(9);
|
||||||
|
var outBuffer = Buffer.alloc(93);
|
||||||
|
outBuffer.writeUInt8(192, 0);
|
||||||
|
outBuffer.writeUInt32BE(1, 1);
|
||||||
|
outBuffer.writeUInt32BE(0, 5);
|
||||||
|
outBuffer.writeUInt32BE(reason, 9);
|
||||||
|
//console.log('Answering PROTOCOL_VERSION');
|
||||||
|
this.write(outBuffer);
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_WINDOW_ADJUST:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
var bytesToAdd = chunk.readUInt32BE(5);
|
||||||
|
if (this.sockets[rChannelId] != undefined) {
|
||||||
|
this.sockets[rChannelId].lme.txWindow += bytesToAdd;
|
||||||
|
if (!this.sockets[rChannelId].bufferedStream.isEmpty() && this.sockets[rChannelId].bufferedStream.isWaiting()) {
|
||||||
|
this.sockets[rChannelId].bufferedStream.emit('readable');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_DATA:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
var dataLen = chunk.readUInt32BE(5);
|
||||||
|
var data = chunk.slice(9, 9 + dataLen);
|
||||||
|
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
|
||||||
|
this.sockets[rChannelId].pendingBytes.push(data.length);
|
||||||
|
this.sockets[rChannelId].write(data, function () {
|
||||||
|
var written = this.pendingBytes.shift();
|
||||||
|
//console.log('adjust', this.lme.amtId, written);
|
||||||
|
var outBuffer = Buffer.alloc(9);
|
||||||
|
outBuffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
|
||||||
|
outBuffer.writeUInt32BE(this.lme.amtId, 1);
|
||||||
|
outBuffer.writeUInt32BE(written, 5);
|
||||||
|
this.HECI.write(outBuffer);
|
||||||
|
});
|
||||||
|
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
|
||||||
|
var channel = this.insockets[rChannelId];
|
||||||
|
if (channel.data == null) { channel.data = data.toString(); } else { channel.data += data.toString(); }
|
||||||
|
channel.rxWindow += dataLen;
|
||||||
|
//console.log('IN DATA', channel.rxWindow, channel.data.length, dataLen, channel.amtId, data.toString());
|
||||||
|
var httpData = parseHttp(channel.data);
|
||||||
|
if ((httpData != null) || (channel.data.length >= 8000)) {
|
||||||
|
// Parse the WSMAN
|
||||||
|
var notify = null;
|
||||||
|
try { notify = xmlParser.ParseWsman(httpData); } catch (e) { }
|
||||||
|
|
||||||
|
// Event the http data
|
||||||
|
if (notify != null) { this.LMS.emit('notify', notify, channel.options, _lmsNotifyToString(notify), _lmsNotifyToCode(notify)); }
|
||||||
|
|
||||||
|
// Send channel close
|
||||||
|
var buffer = Buffer.alloc(5);
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
|
||||||
|
buffer.writeUInt32BE(amtId, 1);
|
||||||
|
this.write(buffer);
|
||||||
|
} else {
|
||||||
|
if (channel.rxWindow > 6000) {
|
||||||
|
// Send window adjust
|
||||||
|
var buffer = Buffer.alloc(9);
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
|
||||||
|
buffer.writeUInt32BE(channel.amtId, 1);
|
||||||
|
buffer.writeUInt32BE(channel.rxWindow, 5);
|
||||||
|
this.write(buffer);
|
||||||
|
channel.rxWindow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_OPEN_FAILURE:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
var reasonCode = chunk.readUInt32BE(5);
|
||||||
|
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
|
||||||
|
this.sockets[rChannelId].end();
|
||||||
|
delete this.sockets[rChannelId];
|
||||||
|
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
|
||||||
|
delete this.insockets[rChannelId];
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_OPEN_FAILURE');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_CLOSE:
|
||||||
|
var rChannelId = chunk.readUInt32BE(1);
|
||||||
|
if ((this.sockets != null) && (this.sockets[rChannelId] != undefined)) {
|
||||||
|
this.sockets[rChannelId].end();
|
||||||
|
var amtId = this.sockets[rChannelId].lme.amtId;
|
||||||
|
var buffer = Buffer.alloc(5);
|
||||||
|
delete this.sockets[rChannelId];
|
||||||
|
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0); // ????????????????????????????
|
||||||
|
buffer.writeUInt32BE(amtId, 1);
|
||||||
|
this.write(buffer);
|
||||||
|
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
|
||||||
|
delete this.insockets[rChannelId];
|
||||||
|
// Should I send a close back????
|
||||||
|
} else {
|
||||||
|
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_CLOSE');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case APF_CHANNEL_OPEN:
|
||||||
|
var nameLen = chunk.readUInt32BE(1);
|
||||||
|
var name = chunk.slice(5, nameLen + 5).toString();
|
||||||
|
var channelSender = chunk.readUInt32BE(nameLen + 5);
|
||||||
|
var initialWindowSize = chunk.readUInt32BE(nameLen + 9);
|
||||||
|
var hostToConnectLen = chunk.readUInt32BE(nameLen + 17);
|
||||||
|
var hostToConnect = chunk.slice(nameLen + 21, nameLen + 21 + hostToConnectLen).toString();
|
||||||
|
var portToConnect = chunk.readUInt32BE(nameLen + 21 + hostToConnectLen);
|
||||||
|
var originatorIpLen = chunk.readUInt32BE(nameLen + 25 + hostToConnectLen);
|
||||||
|
var originatorIp = chunk.slice(nameLen + 29 + hostToConnectLen, nameLen + 29 + hostToConnectLen + originatorIpLen).toString();
|
||||||
|
var originatorPort = chunk.readUInt32BE(nameLen + 29 + hostToConnectLen + originatorIpLen);
|
||||||
|
//console.log('APF_CHANNEL_OPEN', name, channelSender, initialWindowSize, 'From: ' + originatorIp + ':' + originatorPort, 'To: ' + hostToConnect + ':' + portToConnect);
|
||||||
|
|
||||||
|
if (this.insockets == null) { this.insockets = {}; }
|
||||||
|
var ourId = ++lme_id;
|
||||||
|
var insocket = new lme_object();
|
||||||
|
insocket.ourId = ourId;
|
||||||
|
insocket.amtId = channelSender;
|
||||||
|
insocket.txWindow = initialWindowSize;
|
||||||
|
insocket.rxWindow = 0;
|
||||||
|
insocket.options = { target: hostToConnect, targetPort: portToConnect, source: originatorIp, sourcePort: originatorPort };
|
||||||
|
this.insockets[ourId] = insocket;
|
||||||
|
|
||||||
|
var buffer = Buffer.alloc(17);
|
||||||
|
buffer.writeUInt8(APF_CHANNEL_OPEN_CONFIRMATION, 0);
|
||||||
|
buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel
|
||||||
|
buffer.writeUInt32BE(ourId, 5); // Our receiver channel id
|
||||||
|
buffer.writeUInt32BE(4000, 9); // Initial Window Size
|
||||||
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.LMS.emit('connect');
|
||||||
|
this.resume();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bindDuplexStream = function (duplexStream, remoteFamily, localPort) {
|
||||||
|
var socket = duplexStream;
|
||||||
|
//console.log('New [' + remoteFamily + '] Virtual Connection/' + socket.localPort);
|
||||||
|
socket.pendingBytes = [];
|
||||||
|
socket.HECI = this._LME;
|
||||||
|
socket.LMS = this;
|
||||||
|
socket.lme = new lme_object();
|
||||||
|
socket.lme.Socket = socket;
|
||||||
|
socket.localPort = localPort;
|
||||||
|
var buffer = new MemoryStream();
|
||||||
|
buffer.writeUInt8(0x5A);
|
||||||
|
buffer.writeUInt32BE(15);
|
||||||
|
buffer.write('forwarded-tcpip');
|
||||||
|
buffer.writeUInt32BE(socket.lme.ourId);
|
||||||
|
buffer.writeUInt32BE(this.INITIAL_RXWINDOW_SIZE);
|
||||||
|
buffer.writeUInt32BE(0xFFFFFFFF);
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
if (remoteFamily == 'IPv6') {
|
||||||
|
buffer.writeUInt32BE(3);
|
||||||
|
buffer.write('::1');
|
||||||
|
} else {
|
||||||
|
buffer.writeUInt32BE(9);
|
||||||
|
buffer.write('127.0.0.1');
|
||||||
|
}
|
||||||
|
buffer.writeUInt32BE(localPort);
|
||||||
|
}
|
||||||
|
this._LME.write(buffer.buffer);
|
||||||
|
if (this._LME.sockets == undefined) { this._LME.sockets = {}; }
|
||||||
|
this._LME.sockets[socket.lme.ourId] = socket;
|
||||||
|
socket.pause();
|
||||||
|
};
|
||||||
|
|
||||||
|
this._LME.connect(heci.GUIDS.LME, { noPipeline: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseHttp(httpData) {
|
||||||
|
var i = httpData.indexOf('\r\n\r\n');
|
||||||
|
if ((i == -1) || (httpData.length < (i + 2))) { return null; }
|
||||||
|
var headers = require('http-headers')(httpData.substring(0, i), true);
|
||||||
|
var contentLength = parseInt(headers['content-length']);
|
||||||
|
if (httpData.length >= contentLength + i + 4) { return httpData.substring(i + 4, i + 4 + contentLength); }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lmsNotifyToCode(notify) {
|
||||||
|
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
|
||||||
|
var msgid = notify.Body.MessageID;
|
||||||
|
try { msgid += '-' + notify.Body.MessageArguments[0]; } catch (e) { }
|
||||||
|
return msgid;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lmsNotifyToString(notify) {
|
||||||
|
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
|
||||||
|
var msgid = notify.Body.MessageID;
|
||||||
|
try { msgid += '-' + notify.Body.MessageArguments[0]; } catch (e) { }
|
||||||
|
if (lmsEvents[msgid]) { return lmsEvents[msgid]; }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lmsEvents = {
|
||||||
|
"iAMT0001": "System Defense Policy %1s triggered.",
|
||||||
|
"iAMT0002": "Agent Presence Agent %1s not started.",
|
||||||
|
"iAMT0003": "Agent Presence Agent %1s stopped.",
|
||||||
|
"iAMT0004": "Agent Presence Agent %1s running.",
|
||||||
|
"iAMT0005": "Agent Presence Agent %1s expired.",
|
||||||
|
"iAMT0006": "Agent Presence Agent %1s suspended.",
|
||||||
|
"iAMT0007": "Host software attempt to disable AMT Network link detected.",
|
||||||
|
"iAMT0008": "Host software attempt to disable AMT Network link detected -- Host Network link blocked.",
|
||||||
|
"iAMT0009": "AMT clock or FLASH wear-out protection disabled.",
|
||||||
|
"iAMT0010": "Intel(R) AMT Network Interface %1s heuristics defense slow threshold trespassed.",
|
||||||
|
"iAMT0011": "Intel(R) AMT Network Interface %1s heuristics defense fast threshold trespassed.",
|
||||||
|
"iAMT0012": "Intel(R) AMT Network Interface %1s heuristics defense factory defined threshold trespassed.",
|
||||||
|
"iAMT0013": "Intel(R) AMT Network Interface %1s heuristics defense Encounter timeout expired.",
|
||||||
|
"iAMT0014": "General certificate error.",
|
||||||
|
"iAMT0015": "Certificate expired.",
|
||||||
|
"iAMT0016": "No trusted root certificate.",
|
||||||
|
"iAMT0017": "Not configured to work with server certificate.",
|
||||||
|
"iAMT0018": "Certificate revoked.",
|
||||||
|
"iAMT0019": "RSA exponent too large.",
|
||||||
|
"iAMT0020": "RSA modulus too large.",
|
||||||
|
"iAMT0021": "Unsupported digest.",
|
||||||
|
"iAMT0022": "Distinguished name too long.",
|
||||||
|
"iAMT0023": "Key usage missing.",
|
||||||
|
"iAMT0024": "General SSL handshake error.",
|
||||||
|
"iAMT0025": "General 802.1x error.",
|
||||||
|
"iAMT0026": "AMT Diagnostic AlertEAC error - General NAC error.",
|
||||||
|
"iAMT0027": "AMT Diagnostic AlertEAC error - attempt to get a NAC posture while AMT NAC is disabled.",
|
||||||
|
"iAMT0028": "AMT Diagnostic AlertEAC error - attempt to get a posture of an unsupported type.",
|
||||||
|
"iAMT0029": "Audit log storage is 50% full.",
|
||||||
|
"iAMT0030": "Audit log storage is 75% full.",
|
||||||
|
"iAMT0031": "Audit log storage is 85% full.",
|
||||||
|
"iAMT0032": "Audit log storage is 95% full.",
|
||||||
|
"iAMT0033": "Audit log storage is full.",
|
||||||
|
"iAMT0034": "Firmware Update Event - Partial.",
|
||||||
|
"iAMT0035": "Firmware Update Event - Failure.",
|
||||||
|
"iAMT0036": "Remote connectivity initiated.",
|
||||||
|
"iAMT0037": "ME Presence event.",
|
||||||
|
"iAMT0038-0": "AMT is being unprovisioned using BIOS command.",
|
||||||
|
"iAMT0038-1": "AMT is being unprovisioned using Local MEI command.",
|
||||||
|
"iAMT0038-2": "AMT is being unprovisioned using Local WS-MAN/SOAP command.",
|
||||||
|
"iAMT0038-3": "AMT is being unprovisioned using Remote WS-MAN/SOAP command.",
|
||||||
|
"iAMT0039": "HW Asset Error.",
|
||||||
|
"iAMT0050": "User Notification Alert - General Notification.",
|
||||||
|
"iAMT0050-16": "User Notification Alert - Circuit Breaker notification (CB Drop TX filter hit.).",
|
||||||
|
"iAMT0050-17": "User Notification Alert - Circuit Breaker notification (CB Rate Limit TX filter hit.).",
|
||||||
|
"iAMT0050-18": "User Notification Alert - Circuit Breaker notification (CB Drop RX filter hit.).",
|
||||||
|
"iAMT0050-19": "User Notification Alert - Circuit Breaker notification (CB Rate Limit RX filter hit.).",
|
||||||
|
"iAMT0050-32": "User Notification Alert - EAC notification.",
|
||||||
|
"iAMT0050-48": "User Notification Alert - Remote diagnostics - (Remote Redirection session started - SOL).",
|
||||||
|
"iAMT0050-49": "User Notification Alert - Remote diagnostics - (Remote Redirection session stopped - SOL).",
|
||||||
|
"iAMT0050-50": "User Notification Alert - Remote diagnostics. (Remote Redirection session started - IDE-R).",
|
||||||
|
"iAMT0050-51": "User Notification Alert - Remote diagnostics. (Remote Redirection session stopped - IDE-R).",
|
||||||
|
"iAMT0050-66": "User Notification Alert - WLAN notification (Host profile mismatch - Management Interface ignored).",
|
||||||
|
"iAMT0050-67": "User Notification Alert - WLAN notification (Management device overrides host radio).",
|
||||||
|
"iAMT0050-68": "User Notification Alert - WLAN notification (Host profile security mismatch).",
|
||||||
|
"iAMT0050-69": "User Notification Alert - WLAN notification (Management device relinquishes control over host Radio).",
|
||||||
|
"iAMT0051": "User Notification Alert - SecIo event.",
|
||||||
|
"iAMT0051-0": "User Notification Alert - SecIo event semaphore at host.",
|
||||||
|
"iAMT0051-1": "User Notification Alert - semaphore at ME.",
|
||||||
|
"iAMT0051-2": "User Notification Alert - SecIo event - semaphore timeout.",
|
||||||
|
"iAMT0052": "User Notification Alert - KVM session event.",
|
||||||
|
"iAMT0052-0": "User Notification Alert - KVM session requested.",
|
||||||
|
"iAMT0052-1": "User Notification Alert - KVM session started.",
|
||||||
|
"iAMT0052-2": "User Notification Alert - KVM session stopped.",
|
||||||
|
"iAMT0052-3": "User Notification Alert - KVM data channel.",
|
||||||
|
"iAMT0053": "User Notification Alert - RCS notification.",
|
||||||
|
"iAMT0053-50": "User Notification Alert - RCS notification (HW button pressed. Connection initiated automatically).",
|
||||||
|
"iAMT0053-52": "User Notification Alert - RCS notification (HW button pressed. Connection wasn't initiated automatically).",
|
||||||
|
"iAMT0053-53": "User Notification Alert - RCS notification (Contracts updated).",
|
||||||
|
"iAMT0054": "User Notification Alert - WLAN notification. Wireless Profile sync enablement state changed.",
|
||||||
|
"iAMT0055": "User Notification Alert - Provisioning state change notification.",
|
||||||
|
"iAMT0055-0": "User Notification Alert - Provisioning state change notification - Pre-configuration.",
|
||||||
|
"iAMT0055-1": "User Notification Alert - Provisioning state change notification - In configuration.",
|
||||||
|
"iAMT0055-2": "User Notification Alert - Provisioning state change notification - Post-configuration.",
|
||||||
|
"iAMT0055-3": "User Notification Alert - Provisioning state change notification - Unprovision process has started.",
|
||||||
|
"iAMT0056": "User Notification Alert - System Defense change notification.",
|
||||||
|
"iAMT0057": "User Notification Alert - Network State change notification.",
|
||||||
|
"iAMT0058": "User Notification Alert - Remote Access change notification.",
|
||||||
|
"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is closed.",
|
||||||
|
//"iAMT0058-1": "User Notification Alert - Remote Access change notification - tunnel is open.", // TODO
|
||||||
|
"iAMT0059": "User Notification Alert - KVM enabled event.",
|
||||||
|
"iAMT0059-0": "User Notification Alert - KVM enabled event - KVM disabled.",
|
||||||
|
"iAMT0059-1": "User Notification Alert - KVM enabled event - KVM enabled (both from MEBx and PTNI).",
|
||||||
|
"iAMT0060": "User Notification Alert - SecIO configuration event.",
|
||||||
|
"iAMT0061": "ME FW reset occurred.",
|
||||||
|
"iAMT0062": "User Notification Alert - IpSyncEnabled event.",
|
||||||
|
"iAMT0062-0": "User Notification Alert - IpSyncEnabled event - IpSync disabled.",
|
||||||
|
"iAMT0062-1": "User Notification Alert - IpSyncEnabled event - IpSync enabled.",
|
||||||
|
"iAMT0063": "User Notification Alert - HTTP Proxy sync enabled event.",
|
||||||
|
"iAMT0063-0": "User Notification Alert - HTTP Proxy sync enabled event - HTTP Proxy Sync disabled.",
|
||||||
|
"iAMT0063-1": "User Notification Alert - HTTP Proxy sync enabled event - HTTP Proxy Sync enabled.",
|
||||||
|
"iAMT0064": "User Notification Alert - User Consent event.",
|
||||||
|
"iAMT0064-1": "User Notification Alert - User Consent event - User Consent granted.",
|
||||||
|
"iAMT0064-2": "User Notification Alert - User Consent event - User Consent ended.",
|
||||||
|
"iAMT0067-0": "Graceful Remote Control Operation - Shutdown.",
|
||||||
|
"iAMT0067-1": "Graceful Remote Control Operation - Reset.",
|
||||||
|
"iAMT0067-2": "Graceful Remote Control Operation - Hibernate.",
|
||||||
|
"iAMT0068-0": "Link Protection Notification - No link protection.",
|
||||||
|
"iAMT0068-1": "Link Protection Notification - Passive link protection.",
|
||||||
|
"iAMT0068-2": "Link Protection Notification - High link protection.",
|
||||||
|
"iAMT0069-0": "Local Time Sync Enablement Notification - Local Time Sync Disabled.",
|
||||||
|
"iAMT0069-1": "Local Time Sync Enablement Notification - Local Time Sync Enabled.",
|
||||||
|
"iAMT0070": "Host Reset Triggered by WD Expiration Notification.",
|
||||||
|
"PLAT0004": "The chassis %1s was opened.",
|
||||||
|
"PLAT0005": "The chassis %1s was closed.",
|
||||||
|
"PLAT0006": "The drive bay %1s was opened.",
|
||||||
|
"PLAT0007": "The drive bay %1s was closed.",
|
||||||
|
"PLAT0008": "The I/O card area %1s was opened.",
|
||||||
|
"PLAT0009": "The I/O card area %1s was closed.",
|
||||||
|
"PLAT0010": "The processor area %1s was opened.",
|
||||||
|
"PLAT0011": "The processor area %1s was closed.",
|
||||||
|
"PLAT0012": "The LAN %1s has been disconnected.",
|
||||||
|
"PLAT0013": "The LAN %1s has been connected.",
|
||||||
|
"PLAT0016": "The permission to insert package %1s has been granted.",
|
||||||
|
"PLAT0017": "The permission to insert package %1s has been removed.",
|
||||||
|
"PLAT0018": "The fan card area %1s is open.",
|
||||||
|
"PLAT0019": "The fan card area %1s is closed.",
|
||||||
|
"PLAT0022": "The computer system %1s has detected a secure mode violation.",
|
||||||
|
"PLAT0024": "The computer system %1s has detected a pre-boot user password violation.",
|
||||||
|
"PLAT0026": "The computer system %1s has detected a pre-boot setup password violation.",
|
||||||
|
"PLAT0028": "The computer system %1s has detected a network boot password violation.",
|
||||||
|
"PLAT0030": "The computer system %1s has detected a password violation.",
|
||||||
|
"PLAT0032": "The management controller %1s has detected an out-of-band password violation.",
|
||||||
|
"PLAT0034": "The processor %1s has been added.",
|
||||||
|
"PLAT0035": "The processor %1s has been removed.",
|
||||||
|
"PLAT0036": "An over-temperature condition has been detected on the processor %1s.",
|
||||||
|
"PLAT0037": "An over-temperature condition has been removed on the processor %1s.",
|
||||||
|
"PLAT0038": "The processor %1s is operating in a degraded State.",
|
||||||
|
"PLAT0039": "The processor %1s is no longer operating in a degraded State.",
|
||||||
|
"PLAT0040": "The processor %1s has failed.",
|
||||||
|
"PLAT0042": "The processor %1s has failed.",
|
||||||
|
"PLAT0044": "The processor %1s has failed.",
|
||||||
|
"PLAT0046": "The processor %1s has failed.",
|
||||||
|
"PLAT0048": "The processor %1s has failed.",
|
||||||
|
"PLAT0060": "The processor %1s has been enabled.",
|
||||||
|
"PLAT0061": "The processor %1s has been disabled.",
|
||||||
|
"PLAT0062": "The processor %1s has a configuration mismatch.",
|
||||||
|
"PLAT0064": "A terminator has been detected on the processor %1s.",
|
||||||
|
"PLAT0084": "The Power Supply %1s has been added.",
|
||||||
|
"PLAT0085": "The Power Supply %1s has been removed.",
|
||||||
|
"PLAT0086": "The Power Supply %1s has failed.",
|
||||||
|
"PLAT0088": "Failure predicted on power supply %1s.",
|
||||||
|
"PLAT0096": "The input to power supply %1s has been lost or fallen out of range.",
|
||||||
|
"PLAT0098": "The power supply %1s is operating in an input state that is out of range.",
|
||||||
|
"PLAT0099": "The power supply %1s has returned to a normal input state.",
|
||||||
|
"PLAT0100": "The power supply %1s has lost input.",
|
||||||
|
"PLAT0104": "The power supply %1s has a configuration mismatch.",
|
||||||
|
"PLAT0106": "Power supply %1s has been disabled.",
|
||||||
|
"PLAT0107": "Power supply %1s has been enabled.",
|
||||||
|
"PLAT0108": "Power supply %1s has been power cycled.",
|
||||||
|
"PLAT0110": "Power supply %1s has encountered an error during power down.",
|
||||||
|
"PLAT0112": "Power supply %1s has lost power.",
|
||||||
|
"PLAT0114": "Soft power control has failed for power supply %1s.",
|
||||||
|
"PLAT0116": "Power supply %1s has failed.",
|
||||||
|
"PLAT0118": "Failure predicted on power supply %1s.",
|
||||||
|
"PLAT0120": "Memory subsystem failure.",
|
||||||
|
"PLAT0122": "DIMM missing.",
|
||||||
|
"PLAT0124": "Memory error detected & corrected for DIMM %1s.",
|
||||||
|
"PLAT0128": "Memory DIMM %1s added.",
|
||||||
|
"PLAT0129": "Memory DIMM %1s removed.",
|
||||||
|
"PLAT0130": "Memory DIMM %1s enabled.",
|
||||||
|
"PLAT0131": "Memory DIMM %1s disabled.",
|
||||||
|
"PLAT0134": "Memory parity error for DIMM %1s.",
|
||||||
|
"PLAT0136": "Memory scrub failure for DIMM %1s.",
|
||||||
|
"PLAT0138": "Memory uncorrectable error detected for DIMM %1s.",
|
||||||
|
"PLAT0140": "Memory sparing initiated for DIMM %1s.",
|
||||||
|
"PLAT0141": "Memory sparing concluded for DIMM %1s.",
|
||||||
|
"PLAT0142": "Memory DIMM %1s Throttled.",
|
||||||
|
"PLAT0144": "Memory logging limit reached for DIMM %1s.",
|
||||||
|
"PLAT0145": "Memory logging limit removed for DIMM %1s.",
|
||||||
|
"PLAT0146": "An over-temperature condition has been detected on the Memory DIMM %1s.",
|
||||||
|
"PLAT0147": "An over-temperature condition has been removed on the Memory DIMM %1s.",
|
||||||
|
"PLAT0162": "The drive %1s has been added.",
|
||||||
|
"PLAT0163": "The drive %1s has been removed.",
|
||||||
|
"PLAT0164": "The drive %1s has been disabled due to a detected fault.",
|
||||||
|
"PLAT0167": "The drive %1s has been enabled.",
|
||||||
|
"PLAT0168": "Failure predicted on drive %1s.",
|
||||||
|
"PLAT0170": "Hot spare enabled for %1s.",
|
||||||
|
"PLAT0171": "Hot spare disabled for %1s.",
|
||||||
|
"PLAT0172": "Consistency check has begun for %1s.",
|
||||||
|
"PLAT0173": "Consistency check completed for %1s.",
|
||||||
|
"PLAT0174": "Array %1s is in critical condition.",
|
||||||
|
"PLAT0176": "Array %1s has failed.",
|
||||||
|
"PLAT0177": "Array %1s has been restored.",
|
||||||
|
"PLAT0178": "Rebuild in progress for array %1s.",
|
||||||
|
"PLAT0179": "Rebuild completed for array %1s.",
|
||||||
|
"PLAT0180": "Rebuild Aborted for array %1s.",
|
||||||
|
"PLAT0184": "The system %1s encountered a POST error.",
|
||||||
|
"PLAT0186": "The system %1s encountered a firmware hang.",
|
||||||
|
"PLAT0188": "The system %1s encountered firmware progress.",
|
||||||
|
"PLAT0192": "The log %1s has been disabled.",
|
||||||
|
"PLAT0193": "The log %1s has been enabled.",
|
||||||
|
"PLAT0194": "The log %1s has been disabled.",
|
||||||
|
"PLAT0195": "The log %1s has been enabled.",
|
||||||
|
"PLAT0196": "The log %1s has been disabled.",
|
||||||
|
"PLAT0198": "The log %1s has been enabled.",
|
||||||
|
"PLAT0200": "The log %1s has been cleared.",
|
||||||
|
"PLAT0202": "The log %1s is full.",
|
||||||
|
"PLAT0203": "The log %1s is no longer full.",
|
||||||
|
"PLAT0204": "The log %1s is almost full.",
|
||||||
|
"PLAT0208": "The log %1s has a configuration error.",
|
||||||
|
"PLAT0210": "The system %1s has been reconfigured.",
|
||||||
|
"PLAT0212": "The system %1s has encountered an OEM system boot event.",
|
||||||
|
"PLAT0214": "The system %1s has encountered an unknown system hardware fault.",
|
||||||
|
"PLAT0216": "The system %1s has generated an auxiliary log entry.",
|
||||||
|
"PLAT0218": "The system %1s has executed a PEF action.",
|
||||||
|
"PLAT0220": "The system %1s has synchronized the system clock.",
|
||||||
|
"PLAT0222": "A diagnostic interrupt has occurred on system %1s.",
|
||||||
|
"PLAT0224": "A bus timeout has occurred on system %1s.",
|
||||||
|
"PLAT0226": "An I/O channel check NMI has occurred on system %1s.",
|
||||||
|
"PLAT0228": "A software NMI has occurred on system %1s.",
|
||||||
|
"PLAT0230": "System %1s has recovered from an NMI.",
|
||||||
|
"PLAT0232": "A PCI PERR has occurred on system %1s.",
|
||||||
|
"PLAT0234": "A PCI SERR has occurred on system %1s.",
|
||||||
|
"PLAT0236": "An EISA fail safe timeout occurred on system %1s.",
|
||||||
|
"PLAT0238": "A correctable bus error has occurred on system %1s.",
|
||||||
|
"PLAT0240": "An uncorrectable bus error has occurred on system %1s.",
|
||||||
|
"PLAT0242": "A fatal NMI error has occurred on system %1s.",
|
||||||
|
"PLAT0244": "A fatal bus error has occurred on system %1s.",
|
||||||
|
"PLAT0246": "A bus on system %1s is operating in a degraded state.",
|
||||||
|
"PLAT0247": "A bus on system %1s is no longer operating in a degraded state.",
|
||||||
|
"PLAT0248": "The power button %1s has been pressed.",
|
||||||
|
"PLAT0249": "The power button %1s has been released.",
|
||||||
|
"PLAT0250": "The sleep button %1s has been pressed.",
|
||||||
|
"PLAT0251": "The sleep button %1s has been released.",
|
||||||
|
"PLAT0252": "The reset button %1s has been pressed.",
|
||||||
|
"PLAT0253": "The reset button %1s has been released.",
|
||||||
|
"PLAT0254": "The latch to %1s has been opened.",
|
||||||
|
"PLAT0255": "The latch to %1s has been closed.",
|
||||||
|
"PLAT0256": "The service request %1s has been enabled.",
|
||||||
|
"PLAT0257": "The service request %1s has been completed.",
|
||||||
|
"PLAT0258": "Power control of system %1s has failed.",
|
||||||
|
"PLAT0262": "The network port %1s has been connected.",
|
||||||
|
"PLAT0263": "The network port %1s has been disconnected.",
|
||||||
|
"PLAT0266": "The connector %1s has encountered a configuration error.",
|
||||||
|
"PLAT0267": "The connector %1s configuration error has been repaired.",
|
||||||
|
"PLAT0272": "Power on for system %1s.",
|
||||||
|
"PLAT0274": "Power cycle hard requested for system %1s.",
|
||||||
|
"PLAT0276": "Power cycle soft requested for system %1s.",
|
||||||
|
"PLAT0278": "PXE boot requested for system %1s.",
|
||||||
|
"PLAT0280": "Diagnostics boot requested for system %1s.",
|
||||||
|
"PLAT0282": "System restart requested for system %1s.",
|
||||||
|
"PLAT0284": "System restart begun for system %1s.",
|
||||||
|
"PLAT0286": "No bootable media available for system %1s.",
|
||||||
|
"PLAT0288": "Non-bootable media selected for system %1s.",
|
||||||
|
"PLAT0290": "PXE server not found for system %1s.",
|
||||||
|
"PLAT0292": "User timeout on boot for system %1s.",
|
||||||
|
"PLAT0296": "System %1s boot from floppy initiated.",
|
||||||
|
"PLAT0298": "System %1s boot from local drive initiated.",
|
||||||
|
"PLAT0300": "System %1s boot from PXE on network port initiated.",
|
||||||
|
"PLAT0302": "System %1s boot diagnostics initiated.",
|
||||||
|
"PLAT0304": "System %1s boot from CD initiated.",
|
||||||
|
"PLAT0306": "System %1s boot from ROM initiated.",
|
||||||
|
"PLAT0312": "System %1s boot initiated.",
|
||||||
|
"PLAT0320": "Critical stop during OS load on system %1s.",
|
||||||
|
"PLAT0322": "Run-time critical stop on system %1s.",
|
||||||
|
"PLAT0324": "OS graceful stop on system %1s.",
|
||||||
|
"PLAT0326": "OS graceful shutdown begun on system %1s.",
|
||||||
|
"PLAT0327": "OS graceful shutdown completed on system %1s.",
|
||||||
|
"PLAT0328": "Agent not responding on system %1s.",
|
||||||
|
"PLAT0329": "Agent has begun responding on system %1s.",
|
||||||
|
"PLAT0330": "Fault in slot on system %1s.",
|
||||||
|
"PLAT0331": "Fault condition removed on system %1s.",
|
||||||
|
"PLAT0332": "Identifying slot on system %1s.",
|
||||||
|
"PLAT0333": "Identify stopped on slot for system %1s.",
|
||||||
|
"PLAT0334": "Package installed in slot for system %1s.",
|
||||||
|
"PLAT0336": "Slot empty system %1s.",
|
||||||
|
"PLAT0338": "Slot in system %1s is ready for installation.",
|
||||||
|
"PLAT0340": "Slot in system %1s is ready for removal.",
|
||||||
|
"PLAT0342": "Power is off on slot of system %1s.",
|
||||||
|
"PLAT0344": "Power is on for slot of system %1s.",
|
||||||
|
"PLAT0346": "Removal requested for slot of system %1s.",
|
||||||
|
"PLAT0348": "Interlock activated on slot of system %1s.",
|
||||||
|
"PLAT0349": "Interlock de-asserted on slot of system %1s.",
|
||||||
|
"PLAT0350": "Slot disabled on system %1s.",
|
||||||
|
"PLAT0351": "Slot enabled on system %1s.",
|
||||||
|
"PLAT0352": "Slot of system %1s holds spare.",
|
||||||
|
"PLAT0353": "Slot of system %1s no longer holds spare.",
|
||||||
|
"PLAT0354": "Computer system %1s enabled.",
|
||||||
|
"PLAT0356": "Computer system %1s is in sleep - light mode.",
|
||||||
|
"PLAT0358": "Computer system %1s is in hibernate.",
|
||||||
|
"PLAT0360": "Computer system %1s is in standby.",
|
||||||
|
"PLAT0362": "Computer system %1s is in soft off mode.",
|
||||||
|
"PLAT0364": "Computer system %1s is in hard off mode.",
|
||||||
|
"PLAT0366": "Computer system %1s is sleeping.",
|
||||||
|
"PLAT0368": "Watchdog timer expired for %1s.",
|
||||||
|
"PLAT0370": "Reboot of system initiated by watchdog %1s.",
|
||||||
|
"PLAT0372": "Powering off system initiated by watchdog %1s.",
|
||||||
|
"PLAT0374": "Power cycle of system initiated by watchdog %1s.",
|
||||||
|
"PLAT0376": "Watchdog timer interrupt occurred for %1s.",
|
||||||
|
"PLAT0378": "A page alert has been generated for system %1s.",
|
||||||
|
"PLAT0380": "A LAN alert has been generated for system %1s.",
|
||||||
|
"PLAT0382": "An event trap has been generated for system %1s.",
|
||||||
|
"PLAT0384": "An SNMP trap has been generated for system %1s.",
|
||||||
|
"PLAT0390": "%1s detected as present.",
|
||||||
|
"PLAT0392": "%1s detected as absent.",
|
||||||
|
"PLAT0394": "%1s has been disabled.",
|
||||||
|
"PLAT0395": "%1s has been enabled.",
|
||||||
|
"PLAT0396": "Heartbeat lost for LAN %1s.",
|
||||||
|
"PLAT0397": "Heartbeat detected for LAN %1s.",
|
||||||
|
"PLAT0398": "Sensor %1s is unavailable or degraded on management system.",
|
||||||
|
"PLAT0399": "Sensor %1s has returned to normal on management system.",
|
||||||
|
"PLAT0400": "Controller %1s is unavailable or degraded on management system.",
|
||||||
|
"PLAT0401": "Controller %1s has returned to normal on management system.",
|
||||||
|
"PLAT0402": "Management system %1s is off-line.",
|
||||||
|
"PLAT0404": "Management system %1s is disabled.",
|
||||||
|
"PLAT0405": "Management system %1s is enabled.",
|
||||||
|
"PLAT0406": "Sensor %1s has failed on management system.",
|
||||||
|
"PLAT0408": "FRU %1s has failed on management system.",
|
||||||
|
"PLAT0424": "The battery %1s is critically low.",
|
||||||
|
"PLAT0427": "The battery %1s is no longer critically low.",
|
||||||
|
"PLAT0430": "The battery %1s has been removed from unit.",
|
||||||
|
"PLAT0431": "The battery %1s has been added.",
|
||||||
|
"PLAT0432": "The battery %1s has failed.",
|
||||||
|
"PLAT0434": "Session audit is deactivated on system %1s.",
|
||||||
|
"PLAT0435": "Session audit is activated on system %1s.",
|
||||||
|
"PLAT0436": "A hardware change occurred on system %1s.",
|
||||||
|
"PLAT0438": "A firmware or software change occurred on system %1s.",
|
||||||
|
"PLAT0440": "A hardware incompatibility was detected on system %1s.",
|
||||||
|
"PLAT0442": "A firmware or software incompatibility was detected on system %1s.",
|
||||||
|
"PLAT0444": "Invalid or unsupported hardware was detected on system %1s.",
|
||||||
|
"PLAT0446": "Invalid or unsupported firmware or software was detected on system %1s.",
|
||||||
|
"PLAT0448": "A successful hardware change was detected on system %1s.",
|
||||||
|
"PLAT0450": "A successful software or firmware change was detected on system %1s.",
|
||||||
|
"PLAT0464": "FRU %1s not installed on system.",
|
||||||
|
"PLAT0465": "FRU %1s installed on system.",
|
||||||
|
"PLAT0466": "Activation requested for FRU %1s on system.",
|
||||||
|
"PLAT0467": "FRU %1s on system is active.",
|
||||||
|
"PLAT0468": "Activation in progress for FRU %1s on system.",
|
||||||
|
"PLAT0470": "Deactivation request for FRU %1s on system.",
|
||||||
|
"PLAT0471": "FRU %1s on system is in standby or \"hot spare\" state.",
|
||||||
|
"PLAT0472": "Deactivation in progress for FRU %1s on system.",
|
||||||
|
"PLAT0474": "Communication lost with FRU %1s on system.",
|
||||||
|
"PLAT0476": "Numeric sensor %1s going low (lower non-critical).",
|
||||||
|
"PLAT0478": "Numeric sensor %1s going high (lower non-critical).",
|
||||||
|
"PLAT0480": "Numeric sensor %1s going low (lower critical).",
|
||||||
|
"PLAT0482": "Numeric sensor %1s going high (lower critical).",
|
||||||
|
"PLAT0484": "Numeric sensor %1s going low (lower non-recoverable).",
|
||||||
|
"PLAT0486": "Numeric sensor %1s going high (lower non-critical).",
|
||||||
|
"PLAT0488": "Numeric sensor %1s going low (upper non-critical).",
|
||||||
|
"PLAT0490": "Numeric sensor %1s going high (upper non-critical).",
|
||||||
|
"PLAT0492": "Numeric sensor %1s going low (upper critical).",
|
||||||
|
"PLAT0494": "Numeric sensor %1s going high (upper critical).",
|
||||||
|
"PLAT0496": "Numeric sensor %1s going low (upper non-recoverable).",
|
||||||
|
"PLAT0498": "Numeric sensor %1s going high (upper non-recoverable).",
|
||||||
|
"PLAT0500": "Sensor %1s has transitioned to idle.",
|
||||||
|
"PLAT0502": "Sensor %1s has transitioned to active.",
|
||||||
|
"PLAT0504": "Sensor %1s has transitioned to busy.",
|
||||||
|
"PLAT0508": "Sensor %1s has asserted.",
|
||||||
|
"PLAT0509": "Sensor %1s has de-asserted.",
|
||||||
|
"PLAT0510": "Sensor %1s is asserting predictive failure.",
|
||||||
|
"PLAT0511": "Sensor %1s is de-asserting predictive failure.",
|
||||||
|
"PLAT0512": "Sensor %1s has indicated limit exceeded.",
|
||||||
|
"PLAT0513": "Sensor %1s has indicated limit no longer exceeded.",
|
||||||
|
"PLAT0514": "Sensor %1s has indicated performance met.",
|
||||||
|
"PLAT0516": "Sensor %1s has indicated performance lags.",
|
||||||
|
"PLAT0518": "Sensor %1s has transitioned to normal state.",
|
||||||
|
"PLAT0520": "Sensor %1s has transitioned from normal to non-critical state.",
|
||||||
|
"PLAT0522": "Sensor %1s has transitioned to critical from a less severe state.",
|
||||||
|
"PLAT0524": "Sensor %1s has transitioned to non-recoverable from a less severe state.",
|
||||||
|
"PLAT0526": "Sensor %1s has transitioned to non-critical from a more severe state.",
|
||||||
|
"PLAT0528": "Sensor %1s has transitioned to critical from a non-recoverable state.",
|
||||||
|
"PLAT0530": "Sensor %1s has transitioned to non-recoverable.",
|
||||||
|
"PLAT0532": "Sensor %1s indicates a monitor state.",
|
||||||
|
"PLAT0534": "Sensor %1s has an informational state.",
|
||||||
|
"PLAT0536": "Device %1s has been added.",
|
||||||
|
"PLAT0537": "Device %1s has been removed from unit.",
|
||||||
|
"PLAT0538": "Device %1s has been enabled.",
|
||||||
|
"PLAT0539": "Device %1s has been disabled.",
|
||||||
|
"PLAT0540": "Sensor %1s has indicated a running state.",
|
||||||
|
"PLAT0544": "Sensor %1s has indicated a power off state.",
|
||||||
|
"PLAT0546": "Sensor %1s has indicated an on-line state.",
|
||||||
|
"PLAT0548": "Sensor %1s has indicated an off-line state.",
|
||||||
|
"PLAT0550": "Sensor %1s has indicated an off-duty state.",
|
||||||
|
"PLAT0552": "Sensor %1s has indicated a degraded state.",
|
||||||
|
"PLAT0554": "Sensor %1s has indicated a power save state.",
|
||||||
|
"PLAT0556": "Sensor %1s has indicated an install error.",
|
||||||
|
"PLAT0558": "Redundancy %1s has been lost.",
|
||||||
|
"PLAT0560": "Redundancy %1s has been reduced.",
|
||||||
|
"PLAT0561": "Redundancy %1s has been restored.",
|
||||||
|
"PLAT0562": "%1s has transitioned to a D0 power state.",
|
||||||
|
"PLAT0564": "%1s has transitioned to a D1 power state.",
|
||||||
|
"PLAT0566": "%1s has transitioned to a D2 power state.",
|
||||||
|
"PLAT0568": "%1s has transitioned to a D3 power state.",
|
||||||
|
"PLAT0720": "The System %1s encountered firmware progress - memory initialization entry.",
|
||||||
|
"PLAT0721": "The System %1s encountered firmware progress - memory initialization exit.",
|
||||||
|
"PLAT0722": "The System %1s encountered firmware progress - hard drive initialization entry.",
|
||||||
|
"PLAT0723": "The System %1s encountered firmware progress - hard drive initialization exit.",
|
||||||
|
"PLAT0724": "The System %1s encountered firmware progress - user authentication.",
|
||||||
|
"PLAT0728": "The System %1s encountered firmware progress - USR resource configuration entry.",
|
||||||
|
"PLAT0729": "The System %1s encountered firmware progress - USR resource configuration exit.",
|
||||||
|
"PLAT0730": "The System %1s encountered firmware progress - PCI recource configuration entry.",
|
||||||
|
"PLAT0731": "The System %1s encountered firmware progress - PCI recource configuration exit.",
|
||||||
|
"PLAT0732": "The System %1s encountered firmware progress - Option ROM initialization entry.",
|
||||||
|
"PLAT0733": "The System %1s encountered firmware progress - Option ROM initialization entry exit.",
|
||||||
|
"PLAT0734": "The System %1s encountered firmware progress -video initialization entry entry.",
|
||||||
|
"PLAT0735": "The System %1s encountered firmware progress - video initialization entry exit.",
|
||||||
|
"PLAT0736": "The System %1s encountered firmware progress - cache initialization entry.",
|
||||||
|
"PLAT0737": "The System %1s encountered firmware progress - cache initialization exit.",
|
||||||
|
"PLAT0738": "The System %1s encountered firmware progress - keyboard controller initialization entry.",
|
||||||
|
"PLAT0739": "The System %1s encountered firmware progress - keyboard controller initialization exit.",
|
||||||
|
"PLAT0740": "The System %1s encountered firmware progress - motherboard initialization entry.",
|
||||||
|
"PLAT0741": "The System %1s encountered firmware progress - motherboard initialization exit.",
|
||||||
|
"PLAT0742": "The System %1s encountered firmware progress - floppy disk initialization entry.",
|
||||||
|
"PLAT0743": "The System %1s encountered firmware progress - floppy disk initialization exit.",
|
||||||
|
"PLAT0744": "The System %1s encountered firmware progress - keyboard test entry.",
|
||||||
|
"PLAT0745": "The System %1s encountered firmware progress - keyboard test exit.",
|
||||||
|
"PLAT0746": "The System %1s encountered firmware progress - pointing device test entry.",
|
||||||
|
"PLAT0747": "The System %1s encountered firmware progress - pointing device test exit.",
|
||||||
|
"PLAT0750": "The System %1s encountered firmware progress - dock enable entry.",
|
||||||
|
"PLAT0751": "The System %1s encountered firmware progress - dock enable exit.",
|
||||||
|
"PLAT0752": "The System %1s encountered firmware progress - dock disable entry.",
|
||||||
|
"PLAT0753": "The System %1s encountered firmware progress - dock disable exit.",
|
||||||
|
"PLAT0760": "The System %1s encountered firmware progress - start OS boot process.",
|
||||||
|
"PLAT0762": "The System %1s encountered firmware progress - call OS wake vector.",
|
||||||
|
"PLAT0764": "The System %1s encountered firmware progress - unrecoverable keyboard failure.",
|
||||||
|
"PLAT0766": "The System %1s encountered firmware progress - no video device detected.",
|
||||||
|
"PLAT0768": "The System %1s encountered firmware progress - SMART alert detected on drive.",
|
||||||
|
"PLAT0770": "The System %1s encountered firmware progress - unrecoverable boot device failure.",
|
||||||
|
"PLAT0789": "Corrupt BIOS detected.",
|
||||||
|
"PLAT0790": "The System %1s encountered PCI configuration failure.",
|
||||||
|
"PLAT0791": "The System %1s encountered a video subsystem failure.",
|
||||||
|
"PLAT0792": "The System %1s encountered a storage subsystem failure.",
|
||||||
|
"PLAT0793": "The System %1s encountered a USB subsystem failure.",
|
||||||
|
"PLAT0794": "The System %1s has detected no memory in the system.",
|
||||||
|
"PLAT0795": "The System %1s encountered a motherboard failure.",
|
||||||
|
"PLAT0796": "The System %1s encountered a memory Regulator Voltage Bad.",
|
||||||
|
"PLAT0797": "%1s PCI reset is not deasserting.",
|
||||||
|
"PLAT0798": "%1s Non-Motherboard Regulator Failure.",
|
||||||
|
"PLAT0799": "%1s Power Supply Cable failure.",
|
||||||
|
"PLAT0800": "%1s Motherboard regulator failure.",
|
||||||
|
"PLAT0801": "%1s System component compatibility mismatch."
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = lme_heci;
|
649
agents-new/modules_meshcore/amt-manage.js
Normal file
649
agents-new/modules_meshcore/amt-manage.js
Normal file
@ -0,0 +1,649 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Intel(r) AMT Management
|
||||||
|
* @author Ylian Saint-Hilaire
|
||||||
|
* @version v0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a AmtStackCreateService object, this ia the main Intel AMT communication stack.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function AmtManager(agent, db, isdebug) {
|
||||||
|
var sendConsole = function (msg) { agent.SendCommand({ "action": "msg", "type": "console", "value": msg }); }
|
||||||
|
var debug = function (msg) { if (isdebug) { sendConsole('amt-manager: ' + msg + '<br />'); } }
|
||||||
|
var amtMei = null, amtMeiState = 0;
|
||||||
|
var amtLms = null, amtLmsState = 0;
|
||||||
|
var amtGetVersionResult = null;
|
||||||
|
var oswsstack = null;
|
||||||
|
var osamtstack = null;
|
||||||
|
var amtpolicy = null;
|
||||||
|
var obj = this;
|
||||||
|
obj.state = 0;
|
||||||
|
obj.lmsstate = 0;
|
||||||
|
obj.onStateChange = null;
|
||||||
|
obj.setDebug = function (x) { isdebug = x; }
|
||||||
|
|
||||||
|
// Set current Intel AMT activation policy
|
||||||
|
obj.setPolicy = function (policy) {
|
||||||
|
if (JSON.stringify(amtpolicy) != JSON.stringify(policy)) {
|
||||||
|
amtpolicy = policy;
|
||||||
|
if (applyPolicyTimer == null) { obj.applyPolicy(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to load up the MEI module
|
||||||
|
var rebindToMeiRetrys = 0;
|
||||||
|
obj.reset = function () {
|
||||||
|
++rebindToMeiRetrys;
|
||||||
|
amtMei = null, amtMeiState = 0, amtLms = null, amtLmsState = 0, obj.state = 0, obj.lmsstate = 0;
|
||||||
|
//debug('Binding to MEI');
|
||||||
|
try {
|
||||||
|
var amtMeiLib = require('amt-mei');
|
||||||
|
amtMei = new amtMeiLib();
|
||||||
|
amtMei.on('error', function (e) { debug('MEI error'); amtMei = null; amtMeiState = -1; obj.state = -1; obj.onStateChange(amtMeiState); });
|
||||||
|
amtMei.getVersion(function (result) {
|
||||||
|
if (result == null) {
|
||||||
|
amtMeiState = -1;
|
||||||
|
obj.state = -1;
|
||||||
|
if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
|
||||||
|
if (rebindToMeiRetrys < 10) { setTimeout(obj.reset, 10000); }
|
||||||
|
} else {
|
||||||
|
amtGetVersionResult = result;
|
||||||
|
amtMeiState = 2;
|
||||||
|
obj.state = 2;
|
||||||
|
rebindToMeiRetrys = 0;
|
||||||
|
if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
|
||||||
|
//debug('MEI binded');
|
||||||
|
obj.lmsreset();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (ex) { debug('MEI exception: ' + ex); amtMei = null; amtMeiState = -1; obj.state = -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Intel AMT information using MEI
|
||||||
|
var amtMeiTmpState = null;
|
||||||
|
obj.getAmtInfo = function(func) {
|
||||||
|
if ((amtMei == null) || (amtMeiState < 2)) { if (func != null) { func(null); } return; }
|
||||||
|
try {
|
||||||
|
amtMeiTmpState = { Flags: 0 }; // Flags: 1=EHBC, 2=CCM, 4=ACM
|
||||||
|
amtMei.getProtocolVersion(function (result) { if (result != null) { amtMeiTmpState.MeiVersion = result; } });
|
||||||
|
amtMei.getVersion(function (result) { if (result) { amtMeiTmpState.Versions = {}; for (var version in result.Versions) { amtMeiTmpState.Versions[result.Versions[version].Description] = result.Versions[version].Version; } } });
|
||||||
|
amtMei.getProvisioningMode(function (result) { if (result) { amtMeiTmpState.ProvisioningMode = result.mode; } });
|
||||||
|
amtMei.getProvisioningState(function (result) { if (result) { amtMeiTmpState.ProvisioningState = result.state; } });
|
||||||
|
amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } });
|
||||||
|
amtMei.getControlMode(function (result) { if (result != null) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } } }); // Flag 2 = CCM, 4 = ACM
|
||||||
|
//amtMei.getMACAddresses(function (result) { if (result) { amtMeiTmpState.mac = result; } });
|
||||||
|
amtMei.getLanInterfaceSettings(0, function (result) { if (result) { amtMeiTmpState.net0 = result; } });
|
||||||
|
amtMei.getLanInterfaceSettings(1, function (result) { if (result) { amtMeiTmpState.net1 = result; } });
|
||||||
|
amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { amtMeiTmpState.UUID = result.uuid; } });
|
||||||
|
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } if (func != null) { func(amtMeiTmpState); } });
|
||||||
|
} catch (e) { if (func != null) { func(null); } return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called on MicroLMS Intel AMT user notification
|
||||||
|
var handleAmtNotification = function(notifyMsg) {
|
||||||
|
if ((notifyMsg == null) || (notifyMsg.Body == null) || (notifyMsg.Body.MessageID == null) || (notifyMsg.Body.MessageArguments == null)) return null;
|
||||||
|
var amtMessage = notifyMsg.Body.MessageID, amtMessageArg = notifyMsg.Body.MessageArguments[0], notify = null;
|
||||||
|
|
||||||
|
switch (amtMessage) {
|
||||||
|
case 'iAMT0050': { if (amtMessageArg == '48') { notify = 'Intel® AMT Serial-over-LAN connected'; } else if (amtMessageArg == '49') { notify = 'Intel® AMT Serial-over-LAN disconnected'; } break; } // SOL
|
||||||
|
case 'iAMT0052': { if (amtMessageArg == '1') { notify = 'Intel® AMT KVM connected'; } else if (amtMessageArg == '2') { notify = 'Intel® AMT KVM disconnected'; } break; } // KVM
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sent to the entire group, no sessionid or userid specified.
|
||||||
|
if (notify != null) { agent.SendCommand({ "action": "msg", "type": "notify", "value": notify, "tag": "general" }); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch LMS
|
||||||
|
obj.lmsreset = function () {
|
||||||
|
//debug('Binding to LMS');
|
||||||
|
var amtLms = null, amtLmsState = 0;
|
||||||
|
obj.lmsstate = 0;
|
||||||
|
try {
|
||||||
|
var lme_heci = require('amt-lme');
|
||||||
|
amtLmsState = 1;
|
||||||
|
obj.lmsstate = 1;
|
||||||
|
amtLms = new lme_heci();
|
||||||
|
amtLms.on('error', function (e) { amtLmsState = 0; obj.lmsstate = 0; amtLms = null; debug('LMS error'); setupMeiOsAdmin(1); });
|
||||||
|
amtLms.on('connect', function () { amtLmsState = 2; obj.lmsstate = 2; debug('LMS connected'); setupMeiOsAdmin(2); });
|
||||||
|
//amtLms.on('bind', function (map) { });
|
||||||
|
amtLms.on('notify', function (data, options, str, code) {
|
||||||
|
//debug('LMS notify');
|
||||||
|
if (code == 'iAMT0052-3') {
|
||||||
|
kvmGetData();
|
||||||
|
} else {
|
||||||
|
//if (str != null) { debug('Intel AMT LMS: ' + str); }
|
||||||
|
handleAmtNotification(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) { amtLmsState = -1; obj.lmsstate = -1; amtLms = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// KVM Data Channel
|
||||||
|
//
|
||||||
|
|
||||||
|
var setupMeiOsAdmin = function (state) {
|
||||||
|
//debug('Setup MEI OS Admin');
|
||||||
|
if ((amtMei == null) || (amtMeiState < 2) || (amtGetVersionResult == null)) { return; } // If there is no MEI, don't bother with obj.
|
||||||
|
amtMei.getLocalSystemAccount(function (x) {
|
||||||
|
if (x == null) return;
|
||||||
|
//debug('getLocalSystemAccount ' + JSON.stringify(x));
|
||||||
|
var transport = require('amt-wsman-duk');
|
||||||
|
var wsman = require('amt-wsman');
|
||||||
|
var amt = require('amt');
|
||||||
|
oswsstack = new wsman(transport, '127.0.0.1', 16992, x.user, x.pass, false);
|
||||||
|
osamtstack = new amt(oswsstack);
|
||||||
|
//if (func) { func(state); }
|
||||||
|
|
||||||
|
// We got the $$OsAdmin account setup.
|
||||||
|
amtMeiState = 3;
|
||||||
|
obj.state = 3;
|
||||||
|
if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
|
||||||
|
if (applyPolicyTimer == null) { obj.applyPolicy(); }
|
||||||
|
|
||||||
|
//var AllWsman = "CIM_SoftwareIdentity,IPS_SecIOService,IPS_ScreenSettingData,IPS_ProvisioningRecordLog,IPS_HostBasedSetupService,IPS_HostIPSettings,IPS_IPv6PortSettings".split(',');
|
||||||
|
//osamtstack.BatchEnum(null, AllWsman, startLmsWsmanResponse, null, true);
|
||||||
|
//*************************************
|
||||||
|
// Setup KVM data channel if this is Intel AMT 12 or above
|
||||||
|
var amtver = null;
|
||||||
|
try { for (var i in amtGetVersionResult.Versions) { if (amtGetVersionResult.Versions[i].Description == 'AMT') amtver = parseInt(amtGetVersionResult.Versions[i].Version.split('.')[0]); } } catch (e) { }
|
||||||
|
if ((amtver != null) && (amtver >= 12)) {
|
||||||
|
debug('KVM data channel setup');
|
||||||
|
kvmGetData('skip'); // Clear any previous data, this is a dummy read to about handling old data.
|
||||||
|
obj.kvmTempTimer = setInterval(function () { kvmGetData(); }, 2000); // Start polling for KVM data.
|
||||||
|
kvmSetData(JSON.stringify({ action: 'restart', ver: 1 })); // Send a restart command to advise the console if present that MicroLMS just started.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var kvmGetData = function (tag) {
|
||||||
|
osamtstack.IPS_KVMRedirectionSettingData_DataChannelRead(obj.kvmDataGetResponse, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
var kvmDataGetResponse = function (stack, name, response, status, tag) {
|
||||||
|
if ((tag != 'skip') && (status == 200) && (response.Body.ReturnValue == 0)) {
|
||||||
|
var val = null;
|
||||||
|
try { val = Buffer.from(response.Body.DataMessage, 'base64').toString(); } catch (e) { return }
|
||||||
|
if (val != null) { obj.kvmProcessData(response.Body.RealmsBitmap, response.Body.MessageId, val); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var webRtcDesktop = null;
|
||||||
|
var kvmProcessData = function (realms, messageId, val) {
|
||||||
|
var data = null;
|
||||||
|
try { data = JSON.parse(val) } catch (e) { }
|
||||||
|
if ((data != null) && (data.action)) {
|
||||||
|
if (data.action == 'present') { kvmSetData(JSON.stringify({ action: 'present', ver: 1, platform: process.platform })); }
|
||||||
|
if (data.action == 'offer') {
|
||||||
|
webRtcDesktop = {};
|
||||||
|
var rtc = require('ILibWebRTC');
|
||||||
|
webRtcDesktop.webrtc = rtc.createConnection();
|
||||||
|
webRtcDesktop.webrtc.on('connected', function () { });
|
||||||
|
webRtcDesktop.webrtc.on('disconnected', function () { obj.webRtcCleanUp(); });
|
||||||
|
webRtcDesktop.webrtc.on('dataChannel', function (rtcchannel) {
|
||||||
|
webRtcDesktop.rtcchannel = rtcchannel;
|
||||||
|
webRtcDesktop.kvm = mesh.getRemoteDesktopStream();
|
||||||
|
webRtcDesktop.kvm.pipe(webRtcDesktop.rtcchannel, { dataTypeSkip: 1, end: false });
|
||||||
|
webRtcDesktop.rtcchannel.on('end', function () { obj.webRtcCleanUp(); });
|
||||||
|
webRtcDesktop.rtcchannel.on('data', function (x) { obj.kvmCtrlData(this, x); });
|
||||||
|
webRtcDesktop.rtcchannel.pipe(webRtcDesktop.kvm, { dataTypeSkip: 1, end: false });
|
||||||
|
//webRtcDesktop.kvm.on('end', function () { debug('WebRTC DataChannel closed2'); obj.webRtcCleanUp(); });
|
||||||
|
//webRtcDesktop.rtcchannel.on('data', function (data) { debug('WebRTC data: ' + data); });
|
||||||
|
});
|
||||||
|
kvmSetData(JSON.stringify({ action: 'answer', ver: 1, sdp: webRtcDesktop.webrtc.setOffer(data.sdp) }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process KVM control channel data
|
||||||
|
var kvmCtrlData = function (channel, cmd) {
|
||||||
|
if (cmd.length > 0 && cmd.charCodeAt(0) != 123) {
|
||||||
|
// This is upload data
|
||||||
|
if (obj.fileupload != null) {
|
||||||
|
cmd = Buffer.from(cmd, 'base64');
|
||||||
|
var header = cmd.readUInt32BE(0);
|
||||||
|
if ((header == 0x01000000) || (header == 0x01000001)) {
|
||||||
|
fs.writeSync(obj.fileupload.fp, cmd.slice(4));
|
||||||
|
channel.write({ action: 'upload', sub: 'ack', reqid: obj.fileupload.reqid });
|
||||||
|
if (header == 0x01000001) { fs.closeSync(obj.fileupload.fp); obj.fileupload = null; } // Close the file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug('KVM Ctrl Data: ' + cmd);
|
||||||
|
//sendConsoleText('KVM Ctrl Data: ' + cmd);
|
||||||
|
|
||||||
|
try { cmd = JSON.parse(cmd); } catch (ex) { debug('Invalid JSON: ' + cmd); return; }
|
||||||
|
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
|
||||||
|
switch (cmd.action) {
|
||||||
|
case 'ping': {
|
||||||
|
// This is a keep alive
|
||||||
|
channel.write({ action: 'pong' });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'lock': {
|
||||||
|
// Lock the current user out of the desktop
|
||||||
|
if (process.platform == 'win32') { var child = require('child_process'); child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'RunDll32.exe user32.dll,LockWorkStation'], { type: 1 }); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'ls': {
|
||||||
|
/*
|
||||||
|
// Close the watcher if required
|
||||||
|
var samepath = ((obj.httprequest.watcher != undefined) && (cmd.path == obj.httprequest.watcher.path));
|
||||||
|
if ((obj.httprequest.watcher != undefined) && (samepath == false)) {
|
||||||
|
//console.log('Closing watcher: ' + obj.httprequest.watcher.path);
|
||||||
|
//obj.httprequest.watcher.close(); // TODO: This line causes the agent to crash!!!!
|
||||||
|
delete obj.httprequest.watcher;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Send the folder content to the browser
|
||||||
|
var response = getDirectoryInfo(cmd.path);
|
||||||
|
if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
|
||||||
|
channel.write(response);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Start the directory watcher
|
||||||
|
if ((cmd.path != '') && (samepath == false)) {
|
||||||
|
var watcher = fs.watch(cmd.path, onFileWatcher);
|
||||||
|
watcher.tunnel = obj.httprequest;
|
||||||
|
watcher.path = cmd.path;
|
||||||
|
obj.httprequest.watcher = watcher;
|
||||||
|
//console.log('Starting watcher: ' + obj.httprequest.watcher.path);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'mkdir': {
|
||||||
|
// Create a new empty folder
|
||||||
|
fs.mkdirSync(cmd.path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rm': {
|
||||||
|
// Remove many files or folders
|
||||||
|
for (var i in cmd.delfiles) {
|
||||||
|
var fullpath = path.join(cmd.path, cmd.delfiles[i]);
|
||||||
|
try { fs.unlinkSync(fullpath); } catch (e) { debug(e); }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rename': {
|
||||||
|
// Rename a file or folder
|
||||||
|
try { fs.renameSync(path.join(cmd.path, cmd.oldname), path.join(cmd.path, cmd.newname)); } catch (e) { debug(e); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'download': {
|
||||||
|
// Download a file, to browser
|
||||||
|
var sendNextBlock = 0;
|
||||||
|
if (cmd.sub == 'start') { // Setup the download
|
||||||
|
if (obj.filedownload != null) { channel.write({ action: 'download', sub: 'cancel', id: obj.filedownload.id }); delete obj.filedownload; }
|
||||||
|
obj.filedownload = { id: cmd.id, path: cmd.path, ptr: 0 }
|
||||||
|
try { obj.filedownload.f = fs.openSync(obj.filedownload.path, 'rbN'); } catch (e) { channel.write({ action: 'download', sub: 'cancel', id: obj.filedownload.id }); delete obj.filedownload; }
|
||||||
|
if (obj.filedownload) { channel.write({ action: 'download', sub: 'start', id: cmd.id }); }
|
||||||
|
} else if ((obj.filedownload != null) && (cmd.id == obj.filedownload.id)) { // Download commands
|
||||||
|
if (cmd.sub == 'startack') { sendNextBlock = 8; } else if (cmd.sub == 'stop') { delete obj.filedownload; } else if (cmd.sub == 'ack') { sendNextBlock = 1; }
|
||||||
|
}
|
||||||
|
// Send the next download block(s)
|
||||||
|
while (sendNextBlock > 0) {
|
||||||
|
sendNextBlock--;
|
||||||
|
var buf = Buffer.alloc(4096);
|
||||||
|
var len = fs.readSync(obj.filedownload.f, buf, 4, 4092, null);
|
||||||
|
obj.filedownload.ptr += len;
|
||||||
|
if (len < 4092) { buf.writeInt32BE(0x01000001, 0); fs.closeSync(obj.filedownload.f); delete obj.filedownload; sendNextBlock = 0; } else { buf.writeInt32BE(0x01000000, 0); }
|
||||||
|
channel.write(buf.slice(0, len + 4).toString('base64')); // Write as Base64
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'upload': {
|
||||||
|
// Upload a file, from browser
|
||||||
|
if (cmd.sub == 'start') { // Start the upload
|
||||||
|
if (obj.fileupload != null) { fs.closeSync(obj.fileupload.fp); }
|
||||||
|
if (!cmd.path || !cmd.name) break;
|
||||||
|
obj.fileupload = { reqid: cmd.reqid };
|
||||||
|
var filepath = path.join(cmd.path, cmd.name);
|
||||||
|
try { obj.fileupload.fp = fs.openSync(filepath, 'wbN'); } catch (e) { }
|
||||||
|
if (obj.fileupload.fp) { channel.write({ action: 'upload', sub: 'start', reqid: obj.fileupload.reqid }); } else { obj.fileupload = null; channel.write({ action: 'upload', sub: 'error', reqid: obj.fileupload.reqid }); }
|
||||||
|
}
|
||||||
|
else if (cmd.sub == 'cancel') { // Stop the upload
|
||||||
|
if (obj.fileupload != null) { fs.closeSync(obj.fileupload.fp); obj.fileupload = null; }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'copy': {
|
||||||
|
// Copy a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'move': {
|
||||||
|
// Move a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
debug('Invalid KVM command: ' + cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var webRtcCleanUp = function () {
|
||||||
|
debug('webRtcCleanUp');
|
||||||
|
if (webRtcDesktop == null) return;
|
||||||
|
if (webRtcDesktop.rtcchannel) {
|
||||||
|
try { webRtcDesktop.rtcchannel.close(); } catch (e) { }
|
||||||
|
try { webRtcDesktop.rtcchannel.removeAllListeners('data'); } catch (e) { }
|
||||||
|
try { webRtcDesktop.rtcchannel.removeAllListeners('end'); } catch (e) { }
|
||||||
|
delete webRtcDesktop.rtcchannel;
|
||||||
|
}
|
||||||
|
if (webRtcDesktop.webrtc) {
|
||||||
|
try { webRtcDesktop.webrtc.close(); } catch (e) { }
|
||||||
|
try { webRtcDesktop.webrtc.removeAllListeners('connected'); } catch (e) { }
|
||||||
|
try { webRtcDesktop.webrtc.removeAllListeners('disconnected'); } catch (e) { }
|
||||||
|
try { webRtcDesktop.webrtc.removeAllListeners('dataChannel'); } catch (e) { }
|
||||||
|
delete webRtcDesktop.webrtc;
|
||||||
|
}
|
||||||
|
if (webRtcDesktop.kvm) {
|
||||||
|
try { webRtcDesktop.kvm.end(); } catch (e) { }
|
||||||
|
delete webRtcDesktop.kvm;
|
||||||
|
}
|
||||||
|
webRtcDesktop = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var kvmSetData = function (x) {
|
||||||
|
osamtstack.IPS_KVMRedirectionSettingData_DataChannelWrite(Buffer.from(x).toString('base64'), function () { });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a directory with a files and directories within it
|
||||||
|
var deleteFolderRecursive = function(path, rec) {
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
if (rec == true) {
|
||||||
|
fs.readdirSync(obj.path.join(path, '*')).forEach(function (file, index) {
|
||||||
|
var curPath = obj.path.join(path, file);
|
||||||
|
if (fs.statSync(curPath).isDirectory()) { // recurse
|
||||||
|
deleteFolderRecursive(curPath, true);
|
||||||
|
} else { // delete file
|
||||||
|
fs.unlinkSync(curPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fs.unlinkSync(path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Polyfill path.join
|
||||||
|
var path = {
|
||||||
|
join: function () {
|
||||||
|
var x = [];
|
||||||
|
for (var i in arguments) {
|
||||||
|
var w = arguments[i];
|
||||||
|
if (w != null) {
|
||||||
|
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
|
||||||
|
if (i != 0) { while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } }
|
||||||
|
x.push(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x.length == 0) return '/';
|
||||||
|
return x.join('/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function md5hex(str) { return require('MD5Stream').create().syncHash(str).toString('hex'); }
|
||||||
|
|
||||||
|
//
|
||||||
|
// Deactivate Intel AMT CCM
|
||||||
|
//
|
||||||
|
|
||||||
|
// When called, this will use MEI to deactivate Intel AMT when it's in CCM mode. Simply calls "unprovision" on MEI and checks the return code.
|
||||||
|
obj.deactivateCCM = function() {
|
||||||
|
amtMei.unprovision(1, function (status) {
|
||||||
|
if (status == 0) {
|
||||||
|
debug('Success deactivating Intel AMT CCM.');
|
||||||
|
agent.SendCommand({ "action": "coreinfo", "intelamt": { "state": 0, "flags": 0 } });
|
||||||
|
applyPolicyTimer = setTimeout(obj.applyPolicy, 8000);
|
||||||
|
} else {
|
||||||
|
debug('Intel AMT CCM deactivation error: ' + status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Activate Intel AMT to CCM
|
||||||
|
//
|
||||||
|
|
||||||
|
function makePass(length) {
|
||||||
|
var text = "", possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
for (var i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); }
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.activeToCCM = function (adminpass) {
|
||||||
|
if ((adminpass == null) || (adminpass == '')) { adminpass = 'P@0s' + makePass(23); }
|
||||||
|
intelAmtAdminPass = adminpass;
|
||||||
|
//debug('Trying to get local account info...');
|
||||||
|
amtMei.getLocalSystemAccount(function (x) {
|
||||||
|
if ((x != null) && x.user && x.pass) {
|
||||||
|
//debug('Intel AMT local account info: User=' + x.user + ', Pass=' + x.pass + '.');
|
||||||
|
var transport = require('amt-wsman-duk');
|
||||||
|
var wsman = require('amt-wsman');
|
||||||
|
var amt = require('amt');
|
||||||
|
oswsstack = new wsman(transport, '127.0.0.1', 16992, x.user, x.pass, false);
|
||||||
|
osamtstack = new amt(oswsstack);
|
||||||
|
//debug('Trying to get Intel AMT activation information...');
|
||||||
|
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToCCMEx2, adminpass);
|
||||||
|
} else {
|
||||||
|
debug('Unable to get $$OsAdmin password.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeToCCMEx2 = function(stack, name, responses, status, adminpass) {
|
||||||
|
if (status != 200) { debug('Failed to fetch activation information, status ' + status); }
|
||||||
|
else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { debug('Client control mode activation not allowed'); }
|
||||||
|
else { stack.IPS_HostBasedSetupService_Setup(2, md5hex('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + adminpass).substring(0, 32), null, null, null, null, activeToCCMEx3); }
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeToCCMEx3 = function(stack, name, responses, status) {
|
||||||
|
if (status != 200) { debug('Failed to activate, status ' + status); }
|
||||||
|
else if (responses.Body.ReturnValue != 0) { debug('Client control mode activation failed: ' + responses.Body.ReturnValueStr); }
|
||||||
|
else {
|
||||||
|
debug('Intel AMT CCM activation success.');
|
||||||
|
db.Put('amtCCMPass', intelAmtAdminPass);
|
||||||
|
agent.SendCommand({ "action": "coreinfo", "intelamt": { "state": 2, "flags": 2, "user": "admin", "pass": intelAmtAdminPass } });
|
||||||
|
}
|
||||||
|
applyPolicyTimer = setTimeout(obj.applyPolicy, 8000);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.start = function () {
|
||||||
|
// Try to load Intel AMT policy
|
||||||
|
var amtPolicy = null;
|
||||||
|
try { amtPolicy = JSON.parse(db.Get('amtPolicy')); } catch (ex) { debug('Exception loading amtPolicy'); }
|
||||||
|
//if (amtPolicy == null) { debug('no amtPolicy'); } else { debug('Loaded amtPolicy: ' + JSON.stringify(amtPolicy)); }
|
||||||
|
try { intelAmtAdminPass = db.Get('amtCCMPass'); } catch (ex) { }
|
||||||
|
if (typeof intelAmtAdminPass != 'string') { intelAmtAdminPass = null; }
|
||||||
|
obj.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply Intel AMT policy
|
||||||
|
var intelAmtAdminPass, wsstack, amtstack, applyPolicyTimer, policyWsmanRetry = 0;
|
||||||
|
obj.applyPolicy = function () {
|
||||||
|
applyPolicyTimer = null;
|
||||||
|
if ((amtMeiState != 3) || (typeof amtpolicy != 'object') || (typeof amtpolicy.type != 'number') || (amtpolicy.type == 0)) return;
|
||||||
|
if ((amtpolicy.password != null) && (amtpolicy.password != '')) { intelAmtAdminPass = amtpolicy.password; }
|
||||||
|
obj.getAmtInfo(function (meinfo) {
|
||||||
|
if ((amtpolicy.type == 1) && (meinfo.ProvisioningState == 2) && ((meinfo.Flags & 2) != 0)) {
|
||||||
|
// CCM Deactivation Policy.
|
||||||
|
wsstack = null;
|
||||||
|
amtstack = null;
|
||||||
|
obj.deactivateCCM();
|
||||||
|
} else if ((amtpolicy.type == 2) && (meinfo.ProvisioningState == 0)) {
|
||||||
|
// CCM Activation Policy
|
||||||
|
wsstack = null;
|
||||||
|
amtstack = null;
|
||||||
|
if ((amtpolicy.password == null) || (amtpolicy.password == '')) { intelAmtAdminPass = null; }
|
||||||
|
obj.activeToCCM(intelAmtAdminPass);
|
||||||
|
} else if ((amtpolicy.type == 2) && (meinfo.ProvisioningState == 2) && (intelAmtAdminPass != null) && ((meinfo.Flags & 2) != 0)) {
|
||||||
|
// Perform password test
|
||||||
|
var transport = require('amt-wsman-duk');
|
||||||
|
var wsman = require('amt-wsman');
|
||||||
|
var amt = require('amt');
|
||||||
|
wsstack = new wsman(transport, '127.0.0.1', 16992, 'admin', intelAmtAdminPass, false);
|
||||||
|
amtstack = new amt(wsstack);
|
||||||
|
var wsmanQuery = ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService', '*AMT_RedirectionService', '*CIM_KVMRedirectionSAP', 'AMT_PublicKeyCertificate', '*AMT_EnvironmentDetectionSettingData'];
|
||||||
|
if (amtpolicy.cirasetup == 2) { wsmanQuery.push("AMT_ManagementPresenceRemoteSAP", "AMT_RemoteAccessCredentialContext", "AMT_RemoteAccessPolicyAppliesToMPS", "AMT_RemoteAccessPolicyRule", "*AMT_UserInitiatedConnectionService", "AMT_MPSUsernamePassword"); }
|
||||||
|
try { amtstack.BatchEnum(null, wsmanQuery, wsmanPassTestResponse); } catch (ex) { debug(ex); }
|
||||||
|
} else {
|
||||||
|
// Other possible cases...
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function wsmanPassTestResponse(stack, name, responses, status) {
|
||||||
|
if (status != 200) {
|
||||||
|
if (status == 401) {
|
||||||
|
if (amtpolicy.badpass == 1) { obj.deactivateCCM(); } // Incorrect password, reactivate
|
||||||
|
} else {
|
||||||
|
if (++policyWsmanRetry < 20) {
|
||||||
|
if (policyWsmanRetry == 10) { debug('WSMAN fault, MEI Reset'); obj.reset(); }
|
||||||
|
var wsmanQuery = ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService', '*AMT_RedirectionService', '*CIM_KVMRedirectionSAP', 'AMT_PublicKeyCertificate', '*AMT_EnvironmentDetectionSettingData'];
|
||||||
|
if (amtpolicy.cirasetup == 2) { wsmanQuery.push("AMT_ManagementPresenceRemoteSAP", "AMT_RemoteAccessCredentialContext", "AMT_RemoteAccessPolicyAppliesToMPS", "AMT_RemoteAccessPolicyRule", "*AMT_UserInitiatedConnectionService", "AMT_MPSUsernamePassword"); }
|
||||||
|
try { amtstack.BatchEnum(null, wsmanQuery, wsmanPassTestResponse); } catch (ex) { debug(ex); }
|
||||||
|
} else {
|
||||||
|
debug('WSMAN fault, status=' + status);
|
||||||
|
policyWsmanRetry = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
policyWsmanRetry = 0;
|
||||||
|
var s = {};
|
||||||
|
s.redir = (responses['AMT_RedirectionService'].response["ListenerEnabled"] == true);
|
||||||
|
s.sol = ((responses['AMT_RedirectionService'].response["EnabledState"] & 2) != 0);
|
||||||
|
s.ider = ((responses['AMT_RedirectionService'].response["EnabledState"] & 1) != 0);
|
||||||
|
s.kvm = (responses['CIM_KVMRedirectionSAP'] != null) && ((responses['CIM_KVMRedirectionSAP'].response["EnabledState"] == 6 && responses['CIM_KVMRedirectionSAP'].response["RequestedState"] == 2) || responses['CIM_KVMRedirectionSAP'].response["EnabledState"] == 2 || responses['CIM_KVMRedirectionSAP'].response["EnabledState"] == 6);
|
||||||
|
|
||||||
|
// Enable Ping and RMCP if disabled
|
||||||
|
if ((responses['AMT_GeneralSettings'].response['PingResponseEnabled'] != true) || (responses['AMT_GeneralSettings'].response['RmcpPingResponseEnabled'] != true)) {
|
||||||
|
responses['AMT_GeneralSettings'].response['PingResponseEnabled'] = true;
|
||||||
|
responses['AMT_GeneralSettings'].response['RmcpPingResponseEnabled'] = true;
|
||||||
|
amtstack.Put('AMT_GeneralSettings', responses['AMT_GeneralSettings'].response, function (stack, name, response, status) { if (status != 200) { debug("Enable PING PUT Error " + status); } }, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable redirection port, SOL and IDER if needed
|
||||||
|
if ((s.redir == false) || (s.sol == false) || (s.ider == false)) {
|
||||||
|
var r = responses['AMT_RedirectionService'].response;
|
||||||
|
r["ListenerEnabled"] = true; // Turn on the redirection port
|
||||||
|
r["EnabledState"] = 32768 + 1 + 2; // Turn on IDER (1) and SOL (2)
|
||||||
|
amtstack.AMT_RedirectionService_RequestStateChange(r["EnabledState"], function (stack, name, response, status) { if (status != 200) { debug("Enable Redirection EXEC Error " + status); } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable KVM if needed
|
||||||
|
if ((responses['CIM_KVMRedirectionSAP'] != null) && (s.kvm == false)) {
|
||||||
|
amtstack.CIM_KVMRedirectionSAP_RequestStateChange(2, 0,
|
||||||
|
function (stack, name, response, status) {
|
||||||
|
if (status != 200) { messagebox("Error", "KVMRedirectionSAP, RequestStateChange Error " + status); return; }
|
||||||
|
amtstack.Put("AMT_RedirectionService", r, function (stack, name, response, status) { if (status != 200) { debug("Enable KVM PUT Error " + status); } }, 0, 1)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the MeshCentral root certificate is present
|
||||||
|
if (typeof amtpolicy.rootcert == 'string') {
|
||||||
|
var rootFound = false, xxCertificates = responses["AMT_PublicKeyCertificate"].responses;
|
||||||
|
for (var i in xxCertificates) { if ((xxCertificates[i]["X509Certificate"] == amtpolicy.rootcert) && (xxCertificates[i]["TrustedRootCertficate"] == true)) { rootFound = true; } }
|
||||||
|
if (rootFound == false) { amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(amtpolicy.rootcert, function (stack, name, response, status) { if (status != 200) { debug("Add root cert EXEC Error " + status); } }); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// If CIRA needs to be setup
|
||||||
|
if ((amtpolicy.cirasetup == 2) && (amtpolicy.ciraserver != null)) {
|
||||||
|
var serverFound = false, xxCiraServers = responses["AMT_ManagementPresenceRemoteSAP"].responses;
|
||||||
|
for (var i in xxCiraServers) { if ((xxCiraServers[i].AccessInfo == amtpolicy.ciraserver.name) && (xxCiraServers[i].Port == amtpolicy.ciraserver.port)) { serverFound = xxCiraServers[i].Name; } }
|
||||||
|
if (serverFound == false) {
|
||||||
|
// TODO: Remove all CIRA activation policies.
|
||||||
|
// amtstack.Delete('AMT_RemoteAccessPolicyRule', { 'PolicyRuleName': name }, editMpsPolicyOk2);
|
||||||
|
// TODO: Remove all other MPS servers.
|
||||||
|
|
||||||
|
// Add our MPS server
|
||||||
|
amtstack.AMT_RemoteAccessService_AddMpServer(amtpolicy.ciraserver.name, 201, amtpolicy.ciraserver.port, 2, null, amtpolicy.ciraserver.user, amtpolicy.ciraserver.pass, null, function (stack, name, response, status) {
|
||||||
|
if (status != 200) {
|
||||||
|
debug("Add MPS server EXEC Error " + status);
|
||||||
|
} else {
|
||||||
|
serverFound = false;
|
||||||
|
var x = response.Body.MpServer.ReferenceParameters.SelectorSet.Selector;
|
||||||
|
for (var i in x) { if (x[i]['@Name'] == 'Name') { serverFound = x[i]['Value']; } }
|
||||||
|
if (serverFound != false) { checkCiraTriggerPolicy(responses, serverFound); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
checkCiraTriggerPolicy(responses, serverFound);
|
||||||
|
}
|
||||||
|
} else if (amtpolicy.cirasetup == 1) {
|
||||||
|
// This call will clear environement detection if needed.
|
||||||
|
checkEnvironmentDetection(responses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCiraTriggerPolicy(responses, serverInstanceName) {
|
||||||
|
// Check CIRA activation policy
|
||||||
|
var server1 = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="Name">' + serverInstanceName + '</Selector></SelectorSet></ReferenceParameters>';
|
||||||
|
amtstack.AMT_RemoteAccessService_AddRemoteAccessPolicyRule(2, 0, 'AAAAAAAAAAo=', [server1], null, function (stack, name, response, status) {
|
||||||
|
if (status != 200) {
|
||||||
|
debug("Add AddRemoteAccessPolicyRule Error " + status);
|
||||||
|
} else {
|
||||||
|
//debug('AMT_RemoteAccessService_AddRemoteAccessPolicyRule Response:' + JSON.stringify(response));
|
||||||
|
checkEnvironmentDetection(responses);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check environement detection. This will set or clear the environement detection strings as needed.
|
||||||
|
function checkEnvironmentDetection(responses) {
|
||||||
|
var t2 = [];
|
||||||
|
if ((amtpolicy.ciraserver != null) && (amtpolicy.ciraserver.home != null)) { t2 = amtpolicy.ciraserver.home; }
|
||||||
|
var t = responses["AMT_EnvironmentDetectionSettingData"].response;
|
||||||
|
t['DetectionStrings'] = MakeToArray(t['DetectionStrings']);
|
||||||
|
if (CompareStrArrays(t['DetectionStrings'], t2) == false) {
|
||||||
|
t['DetectionStrings'] = t2;
|
||||||
|
amtstack.Put('AMT_EnvironmentDetectionSettingData', t, function (stack, name, response, status) { if (status != 200) { debug("Put AMT_EnvironmentDetectionSettingData Error " + status); } }, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imperfect compare of two string arrays.
|
||||||
|
function CompareStrArrays(arr1, arr2) {
|
||||||
|
if (arr1 == arr2) return true;
|
||||||
|
if (arr1 == null) { arr1 = []; }
|
||||||
|
if (arr2 == null) { arr2 = []; }
|
||||||
|
if (arr1.length != arr2.length) return false;
|
||||||
|
for (var i in arr1) { if (arr2.indexOf(arr1[i]) == -1) return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MakeToArray(v) { if (!v || v == null || typeof v == "object") return v; return [v]; };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AmtManager;
|
418
agents-new/modules_meshcore/amt-mei.js
Normal file
418
agents-new/modules_meshcore/amt-mei.js
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Q = require('queue');
|
||||||
|
function amt_heci() {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
|
||||||
|
var heci = require('heci');
|
||||||
|
var sendConsole = function (msg) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg }); }
|
||||||
|
|
||||||
|
this._ObjectID = "pthi";
|
||||||
|
this._rq = new Q();
|
||||||
|
this._setupPTHI = function _setupPTHI()
|
||||||
|
{
|
||||||
|
this._amt = heci.create();
|
||||||
|
this._amt.BiosVersionLen = 65;
|
||||||
|
this._amt.UnicodeStringLen = 20;
|
||||||
|
|
||||||
|
this._amt.Parent = this;
|
||||||
|
this._amt.on('error', function _amtOnError(e)
|
||||||
|
{
|
||||||
|
if(this.Parent._rq.isEmpty())
|
||||||
|
{
|
||||||
|
this.Parent.emit('error', e); // No pending requests, so propagate the error up
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There is a pending request, so fail the pending request
|
||||||
|
var user = this.Parent._rq.deQueue();
|
||||||
|
var params = user.optional;
|
||||||
|
var callback = user.func;
|
||||||
|
params.unshift({ Status: -1 }); // Relay an error
|
||||||
|
callback.apply(this.Parent, params);
|
||||||
|
|
||||||
|
if(!this.Parent._rq.isEmpty())
|
||||||
|
{
|
||||||
|
// There are still more pending requests, so try to re-helpconnect MEI
|
||||||
|
this.connect(heci.GUIDS.AMT, { noPipeline: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._amt.on('connect', function _amtOnConnect()
|
||||||
|
{
|
||||||
|
this.on('data', function _amtOnData(chunk)
|
||||||
|
{
|
||||||
|
//console.log("Received: " + chunk.length + " bytes");
|
||||||
|
var header = this.Parent.getCommand(chunk);
|
||||||
|
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
|
||||||
|
|
||||||
|
var user = this.Parent._rq.deQueue();
|
||||||
|
var params = user.optional;
|
||||||
|
var callback = user.func;
|
||||||
|
|
||||||
|
params.unshift(header);
|
||||||
|
callback.apply(this.Parent, params);
|
||||||
|
|
||||||
|
if(this.Parent._rq.isEmpty())
|
||||||
|
{
|
||||||
|
// No More Requests, we can close PTHI
|
||||||
|
this.Parent._amt.disconnect();
|
||||||
|
this.Parent._amt = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send the next request
|
||||||
|
this.write(this.Parent._rq.peekQueue().send);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start sending requests
|
||||||
|
this.write(this.Parent._rq.peekQueue().send);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function trim(x) { var y = x.indexOf('\0'); if (y >= 0) { return x.substring(0, y); } else { return x; } }
|
||||||
|
this.getCommand = function getCommand(chunk) {
|
||||||
|
var command = chunk.length == 0 ? (this._rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
|
||||||
|
var ret = { IsResponse: (command & 0x800000) == 0x800000 ? true : false, Command: (command & 0x7FFFFF), Status: chunk.length != 0 ? chunk.readUInt32LE(12) : -1, Data: chunk.length != 0 ? chunk.slice(16) : null };
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sendCommand = function sendCommand()
|
||||||
|
{
|
||||||
|
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
|
||||||
|
var args = [];
|
||||||
|
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
|
||||||
|
|
||||||
|
var header = Buffer.from('010100000000000000000000', 'hex');
|
||||||
|
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
|
||||||
|
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
|
||||||
|
this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args , send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]]))});
|
||||||
|
|
||||||
|
if(!this._amt)
|
||||||
|
{
|
||||||
|
this._setupPTHI();
|
||||||
|
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getVersion = function getVersion(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(26, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var i, CodeVersion = header.Data, val = { BiosVersion: CodeVersion.slice(0, this._amt.BiosVersionLen).toString(), Versions: [] }, v = CodeVersion.slice(this._amt.BiosVersionLen + 4);
|
||||||
|
for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen) ; ++i) {
|
||||||
|
val.Versions[i] = { Description: v.slice(2, v.readUInt16LE(0) + 2).toString(), Version: v.slice(4 + this._amt.UnicodeStringLen, 4 + this._amt.UnicodeStringLen + v.readUInt16LE(2 + this._amt.UnicodeStringLen)).toString() };
|
||||||
|
v = v.slice(4 + (2 * this._amt.UnicodeStringLen));
|
||||||
|
}
|
||||||
|
if (val.BiosVersion.indexOf('\0') > 0) { val.BiosVersion = val.BiosVersion.substring(0, val.BiosVersion.indexOf('\0')); }
|
||||||
|
opt.unshift(val);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getUuid = function getUuid(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x5c, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.uuid = [zeroLeftPad(header.Data.readUInt32LE(0).toString(16), 8),
|
||||||
|
zeroLeftPad(header.Data.readUInt16LE(4).toString(16), 4),
|
||||||
|
zeroLeftPad(header.Data.readUInt16LE(6).toString(16), 4),
|
||||||
|
zeroLeftPad(header.Data.readUInt16BE(8).toString(16), 4),
|
||||||
|
zeroLeftPad(header.Data.slice(10).toString('hex').toLowerCase(), 12)].join('-');
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getProvisioningState = function getProvisioningState(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(17, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.state = header.Data.readUInt32LE(0);
|
||||||
|
if (result.state < 3) { result.stateStr = ["PRE", "IN", "POST"][result.state]; }
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getProvisioningMode = function getProvisioningMode(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(8, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.mode = header.Data.readUInt32LE(0);
|
||||||
|
if (result.mode < 4) { result.modeStr = ["NONE", "ENTERPRISE", "SMALL_BUSINESS", "REMOTE_ASSISTANCE"][result.mode]; }
|
||||||
|
result.legacy = header.Data.readUInt32LE(4) == 0 ? false : true;
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getEHBCState = function getEHBCState(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(132, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
opt.unshift({ EHBC: header.Data.readUInt32LE(0) != 0 });
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getControlMode = function getControlMode(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(107, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.controlMode = header.Data.readUInt32LE(0);
|
||||||
|
if (result.controlMode < 3) { result.controlModeStr = ["NONE_RPAT", "CLIENT", "ADMIN", "REMOTE_ASSISTANCE"][result.controlMode]; }
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getMACAddresses = function getMACAddresses(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(37, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
opt.unshift({ DedicatedMAC: header.Data.slice(0, 6).toString('hex:'), HostMAC: header.Data.slice(6, 12).toString('hex:') });
|
||||||
|
} else { opt.unshift({ DedicatedMAC: null, HostMAC: null }); }
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getDnsSuffix = function getDnsSuffix(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(54, null, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var resultLen = header.Data.readUInt16LE(0);
|
||||||
|
if (resultLen > 0) { opt.unshift(header.Data.slice(2, 2 + resultLen).toString()); } else { opt.unshift(null); }
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getHashHandles = function getHashHandles(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x2C, null, function (header, fn, opt) {
|
||||||
|
var result = [];
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var resultLen = header.Data.readUInt32LE(0);
|
||||||
|
for (var i = 0; i < resultLen; ++i) {
|
||||||
|
result.push(header.Data.readUInt32LE(4 + (4 * i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.unshift(result);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getCertHashEntry = function getCertHashEntry(handle, callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
|
||||||
|
var data = Buffer.alloc(4);
|
||||||
|
data.writeUInt32LE(handle, 0);
|
||||||
|
|
||||||
|
this.sendCommand(0x2D, data, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var result = {};
|
||||||
|
result.isDefault = header.Data.readUInt32LE(0);
|
||||||
|
result.isActive = header.Data.readUInt32LE(4);
|
||||||
|
result.hashAlgorithm = header.Data.readUInt8(72);
|
||||||
|
if (result.hashAlgorithm < 4) {
|
||||||
|
result.hashAlgorithmStr = ["MD5", "SHA1", "SHA256", "SHA512"][result.hashAlgorithm];
|
||||||
|
result.hashAlgorithmSize = [16, 20, 32, 64][result.hashAlgorithm];
|
||||||
|
result.certificateHash = header.Data.slice(8, 8 + result.hashAlgorithmSize).toString('hex');
|
||||||
|
}
|
||||||
|
result.name = header.Data.slice(73 + 2, 73 + 2 + header.Data.readUInt16LE(73)).toString();
|
||||||
|
opt.unshift(result);
|
||||||
|
} else {
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
this.getCertHashEntries = function getCertHashEntries(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
|
||||||
|
this.getHashHandles(function (handles, fn, opt) {
|
||||||
|
var entries = [];
|
||||||
|
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
|
||||||
|
}, callback, optional);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getHashEntrySink = function _getHashEntrySink(result, fn, opt, entries, handles) {
|
||||||
|
entries.push(result);
|
||||||
|
if (handles.length > 0) {
|
||||||
|
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
|
||||||
|
} else {
|
||||||
|
opt.unshift(entries);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.getLocalSystemAccount = function getLocalSystemAccount(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt)
|
||||||
|
{
|
||||||
|
if (header.Status == 0 && header.Data.length == 68)
|
||||||
|
{
|
||||||
|
opt.unshift({ user: trim(header.Data.slice(0, 33).toString()), pass: trim(header.Data.slice(33, 67).toString()), raw: header.Data });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt.unshift(null);
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
}
|
||||||
|
this.getLanInterfaceSettings = function getLanInterfaceSettings(index, callback)
|
||||||
|
{
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
var ifx = Buffer.alloc(4);
|
||||||
|
ifx.writeUInt32LE(index);
|
||||||
|
this.sendCommand(0x48, ifx, function onGetLanInterfaceSettings(header, fn, opt)
|
||||||
|
{
|
||||||
|
if(header.Status == 0)
|
||||||
|
{
|
||||||
|
var info = {};
|
||||||
|
info.enabled = header.Data.readUInt32LE(0);
|
||||||
|
info.dhcpEnabled = header.Data.readUInt32LE(8);
|
||||||
|
switch(header.Data[12])
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
info.dhcpMode = 'ACTIVE'
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
info.dhcpMode = 'PASSIVE'
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
info.dhcpMode = 'UNKNOWN';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
info.mac = header.Data.slice(14).toString('hex:');
|
||||||
|
|
||||||
|
var addr = header.Data.readUInt32LE(4);
|
||||||
|
info.address = ((addr >> 24) & 255) + '.' + ((addr >> 16) & 255) + '.' + ((addr >> 8) & 255) + '.' + (addr & 255);
|
||||||
|
opt.unshift(info);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt.unshift(null);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}
|
||||||
|
}, callback, optional);
|
||||||
|
|
||||||
|
};
|
||||||
|
this.unprovision = function unprovision(mode, callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
var data = Buffer.alloc(4);
|
||||||
|
data.writeUInt32LE(mode, 0);
|
||||||
|
this.sendCommand(16, data, function (header, fn, opt) {
|
||||||
|
opt.unshift(header.Status);
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
}
|
||||||
|
this.startConfiguration = function startConfiguration() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x29, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.stopConfiguration = function stopConfiguration() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x5E, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.openUserInitiatedConnection = function openUserInitiatedConnection() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x44, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.closeUserInitiatedConnection = function closeUnserInitiatedConnected() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x45, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
|
||||||
|
}
|
||||||
|
this.getRemoteAccessConnectionStatus = function getRemoteAccessConnectionStatus() {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
|
||||||
|
this.sendCommand(0x46, data, function (header, fn, opt) {
|
||||||
|
if (header.Status == 0) {
|
||||||
|
var hostname = v.slice(14, header.Data.readUInt16LE(12) + 14).toString()
|
||||||
|
opt.unshift({ status: header.Status, networkStatus: header.Data.readUInt32LE(0), remoteAccessStatus: header.Data.readUInt32LE(4), remoteAccessTrigger: header.Data.readUInt32LE(8), mpsHostname: hostname, raw: header.Data });
|
||||||
|
} else {
|
||||||
|
opt.unshift({ status: header.Status });
|
||||||
|
}
|
||||||
|
fn.apply(this, opt);
|
||||||
|
}, callback, optional);
|
||||||
|
}
|
||||||
|
this.getProtocolVersion = function getProtocolVersion(callback) {
|
||||||
|
var optional = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
|
||||||
|
|
||||||
|
heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
|
||||||
|
if (status == 0) {
|
||||||
|
var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
|
||||||
|
opt.unshift(result);
|
||||||
|
fn.apply(self, opt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opt.unshift(null);
|
||||||
|
fn.apply(self, opt);
|
||||||
|
}
|
||||||
|
}, this, callback, optional);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = amt_heci;
|
105
agents-new/modules_meshcore/amt-scanner.js
Normal file
105
agents-new/modules_meshcore/amt-scanner.js
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Meshcentral Intel AMT Local Scanner
|
||||||
|
* @author Ylian Saint-Hilaire & Joko Sastriawan
|
||||||
|
* @version v0.0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Construct a Intel AMT Scanner object
|
||||||
|
|
||||||
|
function AMTScanner() {
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('found');
|
||||||
|
|
||||||
|
this.dgram = require('dgram');
|
||||||
|
|
||||||
|
this.buildRmcpPing = function (tag) {
|
||||||
|
var packet = Buffer.from('06000006000011BE80000000', 'hex');
|
||||||
|
packet[9] = tag;
|
||||||
|
return packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.parseRmcpPacket = function (server, data, rinfo, func) {
|
||||||
|
if (data == null || data.length < 20) return;
|
||||||
|
var res = {};
|
||||||
|
if (((data[12] == 0) || (data[13] != 0) || (data[14] != 1) || (data[15] != 0x57)) && (data[21] & 32)) {
|
||||||
|
res.servertag = data[9];
|
||||||
|
res.minorVersion = data[18] & 0x0F;
|
||||||
|
res.majorVersion = (data[18] >> 4) & 0x0F;
|
||||||
|
res.provisioningState = data[19] & 0x03; // Pre = 0, In = 1, Post = 2
|
||||||
|
|
||||||
|
var openPort = (data[16] * 256) + data[17];
|
||||||
|
var dualPorts = ((data[19] & 0x04) != 0) ? true : false;
|
||||||
|
res.openPorts = [openPort];
|
||||||
|
res.address = rinfo.address;
|
||||||
|
if (dualPorts == true) { res.openPorts = [16992, 16993]; }
|
||||||
|
if (func !== undefined) {
|
||||||
|
func(server, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parseIPv4Range = function (range) {
|
||||||
|
if (range == undefined || range == null) return null;
|
||||||
|
var x = range.split('-');
|
||||||
|
if (x.length == 2) { return { min: this.parseIpv4Addr(x[0]), max: this.parseIpv4Addr(x[1]) }; }
|
||||||
|
x = range.split('/');
|
||||||
|
if (x.length == 2) {
|
||||||
|
var ip = this.parseIpv4Addr(x[0]), masknum = parseInt(x[1]), mask = 0;
|
||||||
|
if (masknum <= 16 || masknum > 32) return null;
|
||||||
|
masknum = 32 - masknum;
|
||||||
|
for (var i = 0; i < masknum; i++) { mask = (mask << 1); mask++; }
|
||||||
|
return { min: ip & (0xFFFFFFFF - mask), max: (ip & (0xFFFFFFFF - mask)) + mask };
|
||||||
|
}
|
||||||
|
x = this.parseIpv4Addr(range);
|
||||||
|
if (x == null) return null;
|
||||||
|
return { min: x, max: x };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse IP address. Takes a
|
||||||
|
this.parseIpv4Addr = function (addr) {
|
||||||
|
var x = addr.split('.');
|
||||||
|
if (x.length == 4) { return (parseInt(x[0]) << 24) + (parseInt(x[1]) << 16) + (parseInt(x[2]) << 8) + (parseInt(x[3]) << 0); }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP address number to string
|
||||||
|
this.IPv4NumToStr = function (num) {
|
||||||
|
return ((num >> 24) & 0xFF) + '.' + ((num >> 16) & 0xFF) + '.' + ((num >> 8) & 0xFF) + '.' + (num & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scan = function (rangestr, timeout) {
|
||||||
|
var iprange = this.parseIPv4Range(rangestr);
|
||||||
|
var rmcp = this.buildRmcpPing(0);
|
||||||
|
var server = this.dgram.createSocket({ type: 'udp4' });
|
||||||
|
server.parent = this;
|
||||||
|
server.scanResults = [];
|
||||||
|
server.on('error', function (err) { console.log('Error:' + err); });
|
||||||
|
server.on('message', function (msg, rinfo) { if (rinfo.size > 4) { this.parent.parseRmcpPacket(this, msg, rinfo, function (s, res) { s.scanResults.push(res); }) }; });
|
||||||
|
server.on('listening', function () { for (var i = iprange.min; i <= iprange.max; i++) { server.send(rmcp, 623, server.parent.IPv4NumToStr(i)); } });
|
||||||
|
server.bind({ address: '0.0.0.0', port: 0, exclusive: true });
|
||||||
|
var tmout = setTimeout(function cb() {
|
||||||
|
//console.log("Server closed");
|
||||||
|
server.close();
|
||||||
|
server.parent.emit('found', server.scanResults);
|
||||||
|
delete server;
|
||||||
|
}, timeout);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AMTScanner;
|
147
agents-new/modules_meshcore/amt-wsman-duk.js
Normal file
147
agents-new/modules_meshcore/amt-wsman-duk.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description WSMAN communication using duktape http
|
||||||
|
* @author Ylian Saint-Hilaire
|
||||||
|
* @version v0.2.0c
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Construct a WSMAN communication object
|
||||||
|
function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
|
||||||
|
{
|
||||||
|
var obj = {};
|
||||||
|
obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start.
|
||||||
|
obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls
|
||||||
|
obj.MaxActiveAjaxCount = 1; // Maximum number of activate AJAX calls at the same time.
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (arguments.length == 1 && typeof(arguments[0] == 'object'))
|
||||||
|
{
|
||||||
|
obj.host = arguments[0].host;
|
||||||
|
obj.port = arguments[0].port;
|
||||||
|
obj.authToken = arguments[0].authToken;
|
||||||
|
obj.tls = arguments[0].tls;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj.host = arguments[0];
|
||||||
|
obj.port = arguments[1];
|
||||||
|
obj.user = arguments[2];
|
||||||
|
obj.pass = arguments[3];
|
||||||
|
obj.tls = arguments[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
// pri = priority, if set to 1, the call is high priority and put on top of the stack.
|
||||||
|
obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
|
||||||
|
if ((obj.ActiveAjaxCount == 0 || ((obj.ActiveAjaxCount < obj.MaxActiveAjaxCount) && (obj.challengeParams != null))) && obj.PendingAjax.length == 0) {
|
||||||
|
// There are no pending AJAX calls, perform the call now.
|
||||||
|
obj.PerformAjaxEx(postdata, callback, tag, url, action);
|
||||||
|
} else {
|
||||||
|
// If this is a high priority call, put this call in front of the array, otherwise put it in the back.
|
||||||
|
if (pri == 1) { obj.PendingAjax.unshift([postdata, callback, tag, url, action]); } else { obj.PendingAjax.push([postdata, callback, tag, url, action]); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.PerformNextAjax = function () {
|
||||||
|
if (obj.ActiveAjaxCount >= obj.MaxActiveAjaxCount || obj.PendingAjax.length == 0) return;
|
||||||
|
var x = obj.PendingAjax.shift();
|
||||||
|
obj.PerformAjaxEx(x[0], x[1], x[2], x[3], x[4]);
|
||||||
|
obj.PerformNextAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.PerformAjaxEx = function (postdata, callback, tag, url, action) {
|
||||||
|
if (obj.FailAllError != 0) { if (obj.FailAllError != 999) { obj.gotNextMessagesError({ status: obj.FailAllError }, 'error', null, [postdata, callback, tag]); } return; }
|
||||||
|
if (!postdata) postdata = "";
|
||||||
|
//console.log("SEND: " + postdata); // DEBUG
|
||||||
|
|
||||||
|
// We are in a DukTape environement
|
||||||
|
if (obj.digest == null)
|
||||||
|
{
|
||||||
|
if (obj.authToken)
|
||||||
|
{
|
||||||
|
obj.digest = require('http-digest').create({ authToken: obj.authToken });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj.digest = require('http-digest').create(obj.user, obj.pass);
|
||||||
|
}
|
||||||
|
obj.digest.http = require('http');
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
//console.log('Request ' + (obj.RequestCount++));
|
||||||
|
|
||||||
|
req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
|
||||||
|
req.on('response', function (response) {
|
||||||
|
//console.log('Response: ' + response.statusCode);
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
//console.log('ERR:' + JSON.stringify(response));
|
||||||
|
obj.gotNextMessagesError({ status: response.statusCode }, 'error', null, [postdata, callback, tag]);
|
||||||
|
} else {
|
||||||
|
response.acc = '';
|
||||||
|
response.on('data', function (data2) { this.acc += data2; });
|
||||||
|
response.on('end', function () { obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send POST body, this work with binary.
|
||||||
|
req.end(postdata);
|
||||||
|
|
||||||
|
obj.ActiveAjaxCount++;
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AJAX specific private method
|
||||||
|
obj.pendingAjaxCall = [];
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.gotNextMessages = function (data, status, request, callArgs) {
|
||||||
|
obj.ActiveAjaxCount--;
|
||||||
|
if (obj.FailAllError == 999) return;
|
||||||
|
//console.log("RECV: " + data); // DEBUG
|
||||||
|
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
|
||||||
|
if (request.status != 200) { callArgs[1](null, request.status, callArgs[2]); return; }
|
||||||
|
callArgs[1](data, 200, callArgs[2]);
|
||||||
|
obj.PerformNextAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
obj.gotNextMessagesError = function (request, status, errorThrown, callArgs) {
|
||||||
|
obj.ActiveAjaxCount--;
|
||||||
|
if (obj.FailAllError == 999) return;
|
||||||
|
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
|
||||||
|
//if (status != 200) { console.log("ERROR, status=" + status + "\r\n\r\nreq=" + callArgs[0]); } // Debug: Display the request & response if something did not work.
|
||||||
|
if (obj.FailAllError != 999) { callArgs[1]({ Header: { HttpError: request.status } }, request.status, callArgs[2]); }
|
||||||
|
obj.PerformNextAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel all pending queries with given status
|
||||||
|
obj.CancelAllQueries = function (s) {
|
||||||
|
while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CreateWsmanComm;
|
211
agents-new/modules_meshcore/amt-wsman.js
Normal file
211
agents-new/modules_meshcore/amt-wsman.js
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Intel(r) AMT WSMAN Stack
|
||||||
|
* @author Ylian Saint-Hilaire
|
||||||
|
* @version v0.2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Construct a MeshServer object
|
||||||
|
function WsmanStackCreateService(/*CreateWsmanComm, host, port, user, pass, tls, extra*/)
|
||||||
|
{
|
||||||
|
var obj = {_ObjectID: 'WSMAN'};
|
||||||
|
//obj.onDebugMessage = null; // Set to a function if you want to get debug messages.
|
||||||
|
obj.NextMessageId = 1; // Next message number, used to label WSMAN calls.
|
||||||
|
obj.Address = '/wsman';
|
||||||
|
obj.xmlParser = require('amt-xml');
|
||||||
|
|
||||||
|
if (arguments.length == 1 && typeof (arguments[0] == 'object'))
|
||||||
|
{
|
||||||
|
var CreateWsmanComm = arguments[0].transport;
|
||||||
|
if (CreateWsmanComm) { obj.comm = new CreateWsmanComm(arguments[0]); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var CreateWsmanComm = arguments[0];
|
||||||
|
if (CreateWsmanComm) { obj.comm = new CreateWsmanComm(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.PerformAjax = function PerformAjax(postdata, callback, tag, pri, namespaces) {
|
||||||
|
if (namespaces == null) namespaces = '';
|
||||||
|
obj.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns=\"http://www.w3.org/2003/05/soap-envelope\" ' + namespaces + '><Header><a:Action>' + postdata, function (data, status, tag) {
|
||||||
|
if (status != 200) { callback(obj, null, { Header: { HttpError: status } }, status, tag); return; }
|
||||||
|
var wsresponse = obj.xmlParser.ParseWsman(data);
|
||||||
|
if (!wsresponse || wsresponse == null) { callback(obj, null, { Header: { HttpError: status } }, 601, tag); } else { callback(obj, wsresponse.Header["ResourceURI"], wsresponse, 200, tag); }
|
||||||
|
}, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
//obj.Debug = function (msg) { /*console.log(msg);*/ }
|
||||||
|
|
||||||
|
// Cancel all pending queries with given status
|
||||||
|
obj.CancelAllQueries = function CancelAllQueries(s) { obj.comm.CancelAllQueries(s); }
|
||||||
|
|
||||||
|
// Get the last element of a URI string
|
||||||
|
obj.GetNameFromUrl = function (resuri) {
|
||||||
|
var x = resuri.lastIndexOf("/");
|
||||||
|
return (x == -1)?resuri:resuri.substring(x + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN Subscribe operation
|
||||||
|
obj.ExecSubscribe = function ExecSubscribe(resuri, delivery, url, callback, tag, pri, selectors, opaque, user, pass) {
|
||||||
|
var digest = "", digest2 = "", opaque = "";
|
||||||
|
if (user != null && pass != null) { digest = '<t:IssuedTokens xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>' + user + '</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">' + pass + '</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>'; digest2 = '<w:Auth Profile="http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/http/digest"/>'; }
|
||||||
|
if (opaque != null) { opaque = '<a:ReferenceParameters><m:arg>' + opaque + '</m:arg></a:ReferenceParameters>'; }
|
||||||
|
if (delivery == 'PushWithAck') { delivery = 'dmtf.org/wbem/wsman/1/wsman/PushWithAck'; } else if (delivery == 'Push') { delivery = 'xmlsoap.org/ws/2004/08/eventing/DeliveryModes/Push'; }
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>" + _PutObjToSelectorsXml(selectors) + digest + '</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.' + delivery + '"><e:NotifyTo><a:Address>' + url + '</a:Address>' + opaque + '</e:NotifyTo>' + digest2 + '</e:Delivery></e:Subscribe>';
|
||||||
|
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:m="http://x.com"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN UnSubscribe operation
|
||||||
|
obj.ExecUnSubscribe = function ExecUnSubscribe(resuri, callback, tag, pri, selectors) {
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>" + _PutObjToSelectorsXml(selectors) + '</Header><Body><e:Unsubscribe/>';
|
||||||
|
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN PUT operation
|
||||||
|
obj.ExecPut = function ExecPut(resuri, putobj, callback, tag, pri, selectors) {
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + '</Header><Body>' + _PutObjToBodyXml(resuri, putobj);
|
||||||
|
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN CREATE operation
|
||||||
|
obj.ExecCreate = function ExecCreate(resuri, putobj, callback, tag, pri, selectors) {
|
||||||
|
var objname = obj.GetNameFromUrl(resuri);
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + "</Header><Body><g:" + objname + " xmlns:g=\"" + resuri + "\">";
|
||||||
|
for (var n in putobj) { data += "<g:" + n + ">" + putobj[n] + "</g:" + n + ">" }
|
||||||
|
obj.PerformAjax(data + "</g:" + objname + "></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN DELETE operation
|
||||||
|
obj.ExecDelete = function ExecDelete(resuri, putobj, callback, tag, pri) {
|
||||||
|
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(putobj) + "</Header><Body /></Envelope>";
|
||||||
|
obj.PerformAjax(data, callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN GET operation
|
||||||
|
obj.ExecGet = function ExecGet(resuri, callback, tag, pri) {
|
||||||
|
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN method call operation
|
||||||
|
obj.ExecMethod = function ExecMethod(resuri, method, args, callback, tag, pri, selectors) {
|
||||||
|
var argsxml = "";
|
||||||
|
for (var i in args) { if (args[i] != null) { if (Array.isArray(args[i])) { for (var x in args[i]) { argsxml += "<r:" + i + ">" + args[i][x] + "</r:" + i + ">"; } } else { argsxml += "<r:" + i + ">" + args[i] + "</r:" + i + ">"; } } }
|
||||||
|
obj.ExecMethodXml(resuri, method, argsxml, callback, tag, pri, selectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN method call operation. The arguments are already formatted in XML.
|
||||||
|
obj.ExecMethodXml = function ExecMethodXml(resuri, method, argsxml, callback, tag, pri, selectors) {
|
||||||
|
obj.PerformAjax(resuri + "/" + method + "</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + "</Header><Body><r:" + method + '_INPUT' + " xmlns:r=\"" + resuri + "\">" + argsxml + "</r:" + method + "_INPUT></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN ENUM operation
|
||||||
|
obj.ExecEnum = function ExecEnum(resuri, callback, tag, pri) {
|
||||||
|
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\" /></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a WSMAN PULL operation
|
||||||
|
obj.ExecPull = function ExecPull(resuri, enumctx, callback, tag, pri) {
|
||||||
|
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\"><EnumerationContext>" + enumctx + "</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>", callback, tag, pri);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _PutObjToBodyXml(resuri, putObj) {
|
||||||
|
if (!resuri || putObj == null) return '';
|
||||||
|
var objname = obj.GetNameFromUrl(resuri);
|
||||||
|
var result = '<r:' + objname + ' xmlns:r="' + resuri + '">';
|
||||||
|
|
||||||
|
for (var prop in putObj) {
|
||||||
|
if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue;
|
||||||
|
if (putObj[prop] == null || typeof putObj[prop] === 'function') continue;
|
||||||
|
if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) {
|
||||||
|
result += '<r:' + prop + '><a:Address>' + putObj[prop].Address + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + putObj[prop]['ReferenceParameters']["ResourceURI"] + '</w:ResourceURI><w:SelectorSet>';
|
||||||
|
var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector'];
|
||||||
|
if (Array.isArray(selectorArray)) {
|
||||||
|
for (var i=0; i< selectorArray.length; i++) {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet></a:ReferenceParameters></r:' + prop + '>';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Array.isArray(putObj[prop])) {
|
||||||
|
for (var i = 0; i < putObj[prop].length; i++) {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop][i].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += '</r:' + objname + '>';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
convert
|
||||||
|
{ @Name: 'InstanceID', @AttrName: 'Attribute Value'}
|
||||||
|
into
|
||||||
|
' Name="InstanceID" AttrName="Attribute Value" '
|
||||||
|
*/
|
||||||
|
function _ObjectToXmlAttributes(objWithAttributes) {
|
||||||
|
if(!objWithAttributes) return '';
|
||||||
|
var result = ' ';
|
||||||
|
for (var propName in objWithAttributes) {
|
||||||
|
if (!objWithAttributes.hasOwnProperty(propName) || propName.indexOf('@') !== 0) continue;
|
||||||
|
result += propName.substring(1) + '="' + objWithAttributes[propName] + '" ';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _PutObjToSelectorsXml(selectorSet) {
|
||||||
|
if (!selectorSet) return '';
|
||||||
|
if (typeof selectorSet == 'string') return selectorSet;
|
||||||
|
if (selectorSet['InstanceID']) return "<w:SelectorSet><w:Selector Name=\"InstanceID\">" + selectorSet['InstanceID'] + "</w:Selector></w:SelectorSet>";
|
||||||
|
var result = '<w:SelectorSet>';
|
||||||
|
for(var propName in selectorSet) {
|
||||||
|
if (!selectorSet.hasOwnProperty(propName)) continue;
|
||||||
|
result += '<w:Selector Name="' + propName + '">';
|
||||||
|
if (selectorSet[propName]['ReferenceParameters']) {
|
||||||
|
result += '<a:EndpointReference>';
|
||||||
|
result += '<a:Address>' + selectorSet[propName]['Address'] + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + selectorSet[propName]['ReferenceParameters']['ResourceURI'] + '</w:ResourceURI><w:SelectorSet>';
|
||||||
|
var selectorArray = selectorSet[propName]['ReferenceParameters']['SelectorSet']['Selector'];
|
||||||
|
if (Array.isArray(selectorArray)) {
|
||||||
|
for (var i = 0; i < selectorArray.length; i++) {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>';
|
||||||
|
} else {
|
||||||
|
result += selectorSet[propName];
|
||||||
|
}
|
||||||
|
result += '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet>';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WsmanStackCreateService;
|
185
agents-new/modules_meshcore/amt-xml.js
Normal file
185
agents-new/modules_meshcore/amt-xml.js
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Parse XML and return JSON
|
||||||
|
module.exports.ParseWsman = function (xml) {
|
||||||
|
try {
|
||||||
|
if (!xml.childNodes) xml = _turnToXml(xml);
|
||||||
|
var r = { Header: {} }, header = xml.getElementsByTagName("Header")[0], t;
|
||||||
|
if (!header) header = xml.getElementsByTagName("a:Header")[0];
|
||||||
|
if (!header) return null;
|
||||||
|
for (var i = 0; i < header.childNodes.length; i++) {
|
||||||
|
var child = header.childNodes[i];
|
||||||
|
r.Header[child.localName] = child.textContent;
|
||||||
|
}
|
||||||
|
var body = xml.getElementsByTagName("Body")[0];
|
||||||
|
if (!body) body = xml.getElementsByTagName("a:Body")[0];
|
||||||
|
if (!body) return null;
|
||||||
|
if (body.childNodes.length > 0) {
|
||||||
|
t = body.childNodes[0].localName;
|
||||||
|
if (t.indexOf("_OUTPUT") == t.length - 7) { t = t.substring(0, t.length - 7); }
|
||||||
|
r.Header['Method'] = t;
|
||||||
|
r.Body = _ParseWsmanRec(body.childNodes[0]);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Unable to parse XML: " + xml, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private method
|
||||||
|
function _ParseWsmanRec(node) {
|
||||||
|
var data, r = {};
|
||||||
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
|
var child = node.childNodes[i];
|
||||||
|
if ((child.childElementCount == null) || (child.childElementCount == 0)) { data = child.textContent; } else { data = _ParseWsmanRec(child); }
|
||||||
|
if (data == 'true') data = true; // Convert 'true' into true
|
||||||
|
if (data == 'false') data = false; // Convert 'false' into false
|
||||||
|
if ((parseInt(data) + '') === data) data = parseInt(data); // Convert integers
|
||||||
|
|
||||||
|
var childObj = data;
|
||||||
|
if ((child.attributes != null) && (child.attributes.length > 0)) {
|
||||||
|
childObj = { 'Value': data };
|
||||||
|
for (var j = 0; j < child.attributes.length; j++) {
|
||||||
|
childObj['@' + child.attributes[j].name] = child.attributes[j].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r[child.localName] instanceof Array) { r[child.localName].push(childObj); }
|
||||||
|
else if (r[child.localName] == null) { r[child.localName] = childObj; }
|
||||||
|
else { r[child.localName] = [r[child.localName], childObj]; }
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _PutObjToBodyXml(resuri, putObj) {
|
||||||
|
if (!resuri || putObj == null) return '';
|
||||||
|
var objname = obj.GetNameFromUrl(resuri);
|
||||||
|
var result = '<r:' + objname + ' xmlns:r="' + resuri + '">';
|
||||||
|
|
||||||
|
for (var prop in putObj) {
|
||||||
|
if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue;
|
||||||
|
if (putObj[prop] == null || typeof putObj[prop] === 'function') continue;
|
||||||
|
if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) {
|
||||||
|
result += '<r:' + prop + '><a:Address>' + putObj[prop].Address + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + putObj[prop]['ReferenceParameters']["ResourceURI"] + '</w:ResourceURI><w:SelectorSet>';
|
||||||
|
var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector'];
|
||||||
|
if (Array.isArray(selectorArray)) {
|
||||||
|
for (var i = 0; i < selectorArray.length; i++) {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
|
||||||
|
}
|
||||||
|
result += '</w:SelectorSet></a:ReferenceParameters></r:' + prop + '>';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Array.isArray(putObj[prop])) {
|
||||||
|
for (var i = 0; i < putObj[prop].length; i++) {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop][i].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += '<r:' + prop + '>' + putObj[prop].toString() + '</r:' + prop + '>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += '</r:' + objname + '>';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a drop-in replacement to _turnToXml() that works without xml parser dependency.
|
||||||
|
function _treeBuilder() {
|
||||||
|
this.tree = [];
|
||||||
|
this.push = function (element) { this.tree.push(element); };
|
||||||
|
this.pop = function () { var element = this.tree.pop(); if (this.tree.length > 0) { var x = this.tree.peek(); x.childNodes.push(element); x.childElementCount = x.childNodes.length; } return (element); };
|
||||||
|
this.peek = function () { return (this.tree.peek()); }
|
||||||
|
this.addNamespace = function (prefix, namespace) { this.tree.peek().nsTable[prefix] = namespace; if (this.tree.peek().attributes.length > 0) { for (var i = 0; i < this.tree.peek().attributes; ++i) { var a = this.tree.peek().attributes[i]; if (prefix == '*' && a.name == a.localName) { a.namespace = namespace; } else if (prefix != '*' && a.name != a.localName) { var pfx = a.name.split(':')[0]; if (pfx == prefix) { a.namespace = namespace; } } } } }
|
||||||
|
this.getNamespace = function (prefix) { for (var i = this.tree.length - 1; i >= 0; --i) { if (this.tree[i].nsTable[prefix] != null) { return (this.tree[i].nsTable[prefix]); } } return null; }
|
||||||
|
}
|
||||||
|
function _turnToXml(text) { if (text == null) return null; return ({ childNodes: [_turnToXmlRec(text)], getElementsByTagName: _getElementsByTagName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS }); }
|
||||||
|
function _getElementsByTagNameNS(ns, name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name && (node.namespace == ns || ns == '*')) { ret.push(node); } }); return ret; }
|
||||||
|
function _getElementsByTagName(name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name) { ret.push(node); } }); return ret; }
|
||||||
|
function _getChildElementsByTagName(name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name) { ret.push(this.childNodes[node]); } } } return (ret); }
|
||||||
|
function _getChildElementsByTagNameNS(ns, name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name && (ns == '*' || this.childNodes[node].namespace == ns)) { ret.push(this.childNodes[node]); } } } return (ret); }
|
||||||
|
function _xmlTraverseAllRec(nodes, func) { for (var i in nodes) { func(nodes[i]); if (nodes[i].childNodes) { _xmlTraverseAllRec(nodes[i].childNodes, func); } } }
|
||||||
|
function _turnToXmlRec(text) {
|
||||||
|
var elementStack = new _treeBuilder(), lastElement = null, x1 = text.split('<'), ret = [], element = null, currentElementName = null;
|
||||||
|
for (var i in x1) {
|
||||||
|
var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0];
|
||||||
|
if ((elementName.length > 0) && (elementName[0] != '?')) {
|
||||||
|
if (elementName[0] != '/') {
|
||||||
|
var attributes = [], localName, localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0];
|
||||||
|
Object.defineProperty(attributes, "get",
|
||||||
|
{
|
||||||
|
value: function () {
|
||||||
|
if (arguments.length == 1) {
|
||||||
|
for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } }
|
||||||
|
}
|
||||||
|
else if (arguments.length == 2) {
|
||||||
|
for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ('attributes.get(): Invalid number of parameters');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} });
|
||||||
|
// Parse Attributes
|
||||||
|
if (x3.length > 0) {
|
||||||
|
var skip = false;
|
||||||
|
for (var j in x3) {
|
||||||
|
if (x3[j] == '/') {
|
||||||
|
// This is an empty Element
|
||||||
|
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||||
|
elementStack.peek().textContent = '';
|
||||||
|
lastElement = elementStack.pop();
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var k = x3[j].indexOf('=');
|
||||||
|
if (k > 0) {
|
||||||
|
var attrName = x3[j].substring(0, k);
|
||||||
|
var attrValue = x3[j].substring(k + 2, x3[j].length - 1);
|
||||||
|
var attrNS = elementStack.getNamespace('*');
|
||||||
|
|
||||||
|
if (attrName == 'xmlns') {
|
||||||
|
elementStack.addNamespace('*', attrValue);
|
||||||
|
attrNS = attrValue;
|
||||||
|
} else if (attrName.startsWith('xmlns:')) {
|
||||||
|
elementStack.addNamespace(attrName.substring(6), attrValue);
|
||||||
|
} else {
|
||||||
|
var ax = attrName.split(':');
|
||||||
|
if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); }
|
||||||
|
}
|
||||||
|
var x = { name: attrName, value: attrValue }
|
||||||
|
if (attrNS != null) x.namespace = attrNS;
|
||||||
|
elementStack.peek().attributes.push(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip) { continue; }
|
||||||
|
}
|
||||||
|
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||||
|
if (x2[1]) { elementStack.peek().textContent = x2[1]; }
|
||||||
|
} else { lastElement = elementStack.pop(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastElement;
|
||||||
|
}
|
1017
agents-new/modules_meshcore/amt.js
Normal file
1017
agents-new/modules_meshcore/amt.js
Normal file
File diff suppressed because it is too large
Load Diff
128
agents-new/modules_meshcore/linux-dbus.js
Normal file
128
agents-new/modules_meshcore/linux-dbus.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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 read X; do 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;
|
335
agents-new/modules_meshcore/monitor-border.js
Normal file
335
agents-new/modules_meshcore/monitor-border.js
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var red = 0xFF;
|
||||||
|
var yellow = 0xFFFF;
|
||||||
|
var GXxor = 0x6; // src XOR dst
|
||||||
|
var GXclear = 0x0;
|
||||||
|
var ExposureMask = (1 << 15);
|
||||||
|
|
||||||
|
function windows_monitorborder()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'monitor-info';
|
||||||
|
var info = require('monitor-info');
|
||||||
|
var gm = require('_GenericMarshal');
|
||||||
|
var user32 = gm.CreateNativeProxy('user32.dll');
|
||||||
|
|
||||||
|
info.monitors = [];
|
||||||
|
user32.CreateMethod('GetDC');
|
||||||
|
user32.CreateMethod('ReleaseDC');
|
||||||
|
user32.CreateMethod('FillRect');
|
||||||
|
user32.CreateMethod('InvalidateRect');
|
||||||
|
|
||||||
|
var gdi32 = gm.CreateNativeProxy('gdi32.dll');
|
||||||
|
gdi32.CreateMethod('CreateSolidBrush');
|
||||||
|
|
||||||
|
var redBrush = gdi32.CreateSolidBrush(red);
|
||||||
|
var yellowBrush = gdi32.CreateSolidBrush(yellow);
|
||||||
|
|
||||||
|
require('events').EventEmitter.call(this);
|
||||||
|
this.on('~', function () { this.Stop(); });
|
||||||
|
|
||||||
|
this.Stop = function Stop()
|
||||||
|
{
|
||||||
|
info.redInterval = null;
|
||||||
|
|
||||||
|
var drawRect = gm.CreateVariable(16);
|
||||||
|
var drawRectBuffer = drawRect.toBuffer();
|
||||||
|
|
||||||
|
for (var i in info.monitors)
|
||||||
|
{
|
||||||
|
// Top
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + (info.monitors[i].right - info.monitors[i].left), 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom - info.monitors[i].top, 12);
|
||||||
|
user32.InvalidateRect(0, drawRect, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Start = function Start()
|
||||||
|
{
|
||||||
|
info.getInfo().then(function (mon)
|
||||||
|
{
|
||||||
|
var drawRect = gm.CreateVariable(16);
|
||||||
|
|
||||||
|
info.monitors = mon;
|
||||||
|
info.dc = user32.GetDC(0);
|
||||||
|
info.state = 0;
|
||||||
|
|
||||||
|
info.redInterval = setInterval(function ()
|
||||||
|
{
|
||||||
|
info.state = (info.state + 1) % 8;
|
||||||
|
|
||||||
|
var drawRectBuffer = drawRect.toBuffer();
|
||||||
|
for(var i in info.monitors)
|
||||||
|
{
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + (info.monitors[i].right - info.monitors[i].left)/2, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(5, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 0 || info.state == 4) ? yellowBrush : redBrush);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + (info.monitors[i].right - info.monitors[i].left) / 2, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].right, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(5, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 1 || info.state == 5) ? yellowBrush : redBrush);
|
||||||
|
|
||||||
|
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].right - 5, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].right, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top + (info.monitors[i].bottom - info.monitors[i].top)/2, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 2 || info.state == 6) ? yellowBrush : redBrush);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].right - 5, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top + (info.monitors[i].bottom - info.monitors[i].top) / 2, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].right, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 3 || info.state == 7) ? yellowBrush : redBrush);
|
||||||
|
|
||||||
|
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + (info.monitors[i].right - info.monitors[i].left) / 2, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom - 5, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].right, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 4 || info.state == 0) ? yellowBrush : redBrush);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom - 5, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + (info.monitors[i].right - info.monitors[i].left) / 2, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 5 || info.state == 1) ? yellowBrush : redBrush);
|
||||||
|
|
||||||
|
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top + (info.monitors[i].bottom - info.monitors[i].top) / 2, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + 5, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].bottom, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 6 || info.state == 2) ? yellowBrush : redBrush);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left, 0);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top, 4);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].left + 5, 8);
|
||||||
|
drawRectBuffer.writeInt32LE(info.monitors[i].top + (info.monitors[i].bottom - info.monitors[i].top) / 2, 12);
|
||||||
|
user32.FillRect(info.dc, drawRect, (info.state == 7 || info.state == 3) ? yellowBrush : redBrush);
|
||||||
|
}
|
||||||
|
}, 450);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function linux_monitorborder()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
this.displays = [];
|
||||||
|
this._ObjectID = 'monitor-info';
|
||||||
|
this._info = require('monitor-info');
|
||||||
|
this._isUnity = this._info.isUnity();
|
||||||
|
|
||||||
|
console.log('isUnity = ' + this._isUnity);
|
||||||
|
|
||||||
|
require('events').EventEmitter.call(this);
|
||||||
|
this.on('~', function () { this.Stop(); });
|
||||||
|
|
||||||
|
this.Stop = function Stop()
|
||||||
|
{
|
||||||
|
this._timeout = null;
|
||||||
|
if(!this._isUnity)
|
||||||
|
{
|
||||||
|
for(var i=0; i < this.displays.length; ++i)
|
||||||
|
{
|
||||||
|
if(this.displays[i].GC1 && this.displays[i].rootWindow)
|
||||||
|
{
|
||||||
|
self._info._X11.XSetFunction(self.displays[i].display, self.displays[i].GC1, GXclear);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, 0, self.displays[i].right, 0);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, self.displays[i].right, 0, self.displays[i].right, self.displays[i].bottom);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, self.displays[i].bottom, self.displays[i].right, self.displays[i].bottom);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, 0, 0, self.displays[i].bottom);
|
||||||
|
|
||||||
|
this._info._X11.XFlush(this.displays[i].display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Start = function Start()
|
||||||
|
{
|
||||||
|
this._info.getInfo().then(function (mon)
|
||||||
|
{
|
||||||
|
self.displays = mon;
|
||||||
|
console.log(mon.length + ' displays');
|
||||||
|
for(var i = 0; i<mon.length; ++i)
|
||||||
|
{
|
||||||
|
console.log('Width: ' + mon[i].right + ', Height: ' + mon[i].bottom);
|
||||||
|
mon[i].rootWindow = self._info._X11.XRootWindow(mon[i].display, mon[i].screenId);
|
||||||
|
|
||||||
|
if (self._isUnity)
|
||||||
|
{
|
||||||
|
// We are unity, so we have to fake the borders with borderless windows
|
||||||
|
var white = self._info._X11.XWhitePixel(mon[i].display, mon[i].screenId).Val;
|
||||||
|
|
||||||
|
// Top
|
||||||
|
mon[i].window_top = self._info._X11.XCreateSimpleWindow(mon[i].display, mon[i].rootWindow, 0, 0, mon[i].right, 5, 0, white, white);
|
||||||
|
mon[i].window_top.gc = self._info._X11.XCreateGC(mon[i].display, mon[i].window_top, 0, 0);
|
||||||
|
self._info._X11.XSetLineAttributes(mon[i].display, mon[i].window_top.gc, 10, 0, 1, 1);
|
||||||
|
self._info._X11.XSetSubwindowMode(mon[i].display, mon[i].window_top.gc, 1);
|
||||||
|
self._info.unDecorateWindow(mon[i].display, mon[i].window_top);
|
||||||
|
self._info.setWindowSizeHints(mon[i].display, mon[i].window_top, 0, 0, mon[i].right, 5);
|
||||||
|
|
||||||
|
// Right
|
||||||
|
mon[i].window_right = self._info._X11.XCreateSimpleWindow(mon[i].display, mon[i].rootWindow, mon[i].right - 5, 0, 5, mon[i].bottom, 0, white, white);
|
||||||
|
mon[i].window_right.gc = self._info._X11.XCreateGC(mon[i].display, mon[i].window_right, 0, 0);
|
||||||
|
self._info._X11.XSetLineAttributes(mon[i].display, mon[i].window_right.gc, 10, 0, 1, 1);
|
||||||
|
self._info._X11.XSetSubwindowMode(mon[i].display, mon[i].window_right.gc, 1);
|
||||||
|
self._info.unDecorateWindow(mon[i].display, mon[i].window_right);
|
||||||
|
self._info.setWindowSizeHints(mon[i].display, mon[i].window_right, mon[i].right - 5, 0, 5, mon[i].bottom);
|
||||||
|
|
||||||
|
// Left
|
||||||
|
mon[i].window_left = self._info._X11.XCreateSimpleWindow(mon[i].display, mon[i].rootWindow, 0, 0, 5, mon[i].bottom, 0, white, white);
|
||||||
|
mon[i].window_left.gc = self._info._X11.XCreateGC(mon[i].display, mon[i].window_left, 0, 0);
|
||||||
|
self._info._X11.XSetLineAttributes(mon[i].display, mon[i].window_left.gc, 10, 0, 1, 1);
|
||||||
|
self._info._X11.XSetSubwindowMode(mon[i].display, mon[i].window_left.gc, 1);
|
||||||
|
self._info.unDecorateWindow(mon[i].display, mon[i].window_left);
|
||||||
|
self._info.setWindowSizeHints(mon[i].display, mon[i].window_left, 0, 0, 5, mon[i].bottom);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
mon[i].window_bottom = self._info._X11.XCreateSimpleWindow(mon[i].display, mon[i].rootWindow, 0, mon[i].bottom - 5, mon[i].right, 5, 0, white, white);
|
||||||
|
mon[i].window_bottom.gc = self._info._X11.XCreateGC(mon[i].display, mon[i].window_bottom, 0, 0);
|
||||||
|
self._info._X11.XSetLineAttributes(mon[i].display, mon[i].window_bottom.gc, 10, 0, 1, 1);
|
||||||
|
self._info._X11.XSetSubwindowMode(mon[i].display, mon[i].window_bottom.gc, 1);
|
||||||
|
self._info.unDecorateWindow(mon[i].display, mon[i].window_bottom);
|
||||||
|
self._info.setWindowSizeHints(mon[i].display, mon[i].window_bottom, 0, mon[i].bottom - 5, mon[i].right, 5);
|
||||||
|
|
||||||
|
self._info._X11.XMapWindow(mon[i].display, mon[i].window_top);
|
||||||
|
self._info._X11.XMapWindow(mon[i].display, mon[i].window_right);
|
||||||
|
self._info._X11.XMapWindow(mon[i].display, mon[i].window_left);
|
||||||
|
self._info._X11.XMapWindow(mon[i].display, mon[i].window_bottom);
|
||||||
|
|
||||||
|
self._info.setAlwaysOnTop(mon[i].display, mon[i].rootWindow, mon[i].window_top);
|
||||||
|
self._info.hideWindowIcon(mon[i].display, mon[i].rootWindow, mon[i].window_top);
|
||||||
|
self._info.setAlwaysOnTop(mon[i].display, mon[i].rootWindow, mon[i].window_right);
|
||||||
|
self._info.hideWindowIcon(mon[i].display, mon[i].rootWindow, mon[i].window_right);
|
||||||
|
self._info.setAlwaysOnTop(mon[i].display, mon[i].rootWindow, mon[i].window_left);
|
||||||
|
self._info.hideWindowIcon(mon[i].display, mon[i].rootWindow, mon[i].window_left);
|
||||||
|
self._info.setAlwaysOnTop(mon[i].display, mon[i].rootWindow, mon[i].window_bottom);
|
||||||
|
self._info.hideWindowIcon(mon[i].display, mon[i].rootWindow, mon[i].window_bottom);
|
||||||
|
|
||||||
|
self._info._X11.XFlush(mon[i].display);
|
||||||
|
mon[i].borderState = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we aren't unity, then we can just draw
|
||||||
|
mon[i].GC1 = self._info._X11.XCreateGC(mon[i].display, mon[i].rootWindow, 0, 0);
|
||||||
|
mon[i].borderState = 0;
|
||||||
|
|
||||||
|
self._info._X11.XSetForeground(mon[i].display, mon[i].GC1, self._info._X11.XWhitePixel(mon[i].display, mon[i].screenId).Val); // White
|
||||||
|
self._info._X11.XSetLineAttributes(mon[i].display, mon[i].GC1, 10, 0, 1, 1);
|
||||||
|
self._info._X11.XSetSubwindowMode(mon[i].display, mon[i].GC1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self._info._XEvent = self._info._gm.CreateVariable(192);
|
||||||
|
self._timeout = setTimeout(self._isUnity ? self.unity_drawBorder : self.timeoutHandler, 250);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timeoutHandler = function()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < self.displays.length; ++i) {
|
||||||
|
self.displays[i].borderState = (self.displays[i].borderState + 1) % 8;
|
||||||
|
|
||||||
|
// Top
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 0 || self.displays[i].borderState == 4) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, 0, self.displays[i].right / 2, 0);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 1 || self.displays[i].borderState == 5) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, self.displays[i].right / 2, 0, self.displays[i].right, 0);
|
||||||
|
|
||||||
|
// Right
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 2 || self.displays[i].borderState == 6) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, self.displays[i].right, 0, self.displays[i].right, self.displays[i].bottom / 2);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 3 || self.displays[i].borderState == 7) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, self.displays[i].right, self.displays[i].bottom / 2, self.displays[i].right, self.displays[i].bottom);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 5 || self.displays[i].borderState == 1) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, self.displays[i].bottom, self.displays[i].right / 2, self.displays[i].bottom);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 4 || self.displays[i].borderState == 0) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, self.displays[i].right / 2, self.displays[i].bottom, self.displays[i].right, self.displays[i].bottom);
|
||||||
|
|
||||||
|
// Left
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 7 || self.displays[i].borderState == 3) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, 0, 0, self.displays[i].bottom / 2);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].GC1, (self.displays[i].borderState == 6 || self.displays[i].borderState == 2) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].rootWindow, self.displays[i].GC1, 0, self.displays[i].bottom / 2, 0, self.displays[i].bottom);
|
||||||
|
|
||||||
|
|
||||||
|
self._info._X11.XFlush(self.displays[i].display);
|
||||||
|
}
|
||||||
|
self._timeout = setTimeout(self._isUnity ? self.unity_drawBorder : self.timeoutHandler, 400);
|
||||||
|
}
|
||||||
|
this.unity_drawBorder = function unity_drawBorder()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < self.displays.length; ++i)
|
||||||
|
{
|
||||||
|
self.displays[i].borderState = (self.displays[i].borderState + 1) % 8;
|
||||||
|
|
||||||
|
// Top
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_top.gc, (self.displays[i].borderState == 0 || self.displays[i].borderState == 4) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_top, self.displays[i].window_top.gc, 0, 0, self.displays[i].right / 2, 0);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_top.gc, (self.displays[i].borderState == 1 || self.displays[i].borderState == 5) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_top, self.displays[i].window_top.gc, self.displays[i].right / 2, 0, self.displays[i].right, 0);
|
||||||
|
self._info._X11.XFlush(self.displays[i].display);
|
||||||
|
|
||||||
|
// Right
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_right.gc, (self.displays[i].borderState == 2 || self.displays[i].borderState == 6) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_right, self.displays[i].window_right.gc, 0, 0, 0, self.displays[i].bottom / 2);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_right.gc, (self.displays[i].borderState == 3 || self.displays[i].borderState == 7) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_right, self.displays[i].window_right.gc, 0, self.displays[i].bottom / 2, 0, self.displays[i].bottom);
|
||||||
|
self._info._X11.XFlush(self.displays[i].display);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_bottom.gc, (self.displays[i].borderState == 5 || self.displays[i].borderState == 1) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_bottom, self.displays[i].window_bottom.gc, 0, 0, self.displays[i].right / 2, 0);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_bottom.gc, (self.displays[i].borderState == 4 || self.displays[i].borderState == 0) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_bottom, self.displays[i].window_bottom.gc, self.displays[i].right / 2, 0, self.displays[i].right, 0);
|
||||||
|
self._info._X11.XFlush(self.displays[i].display);
|
||||||
|
|
||||||
|
// Left
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_left.gc, (self.displays[i].borderState == 7 || self.displays[i].borderState == 3) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_left, self.displays[i].window_left.gc, 0, 0, 0, self.displays[i].bottom / 2);
|
||||||
|
self._info._X11.XSetForeground(self.displays[i].display, self.displays[i].window_left.gc, (self.displays[i].borderState == 6 || self.displays[i].borderState == 2) ? 0xffff00 : 0xff0000);
|
||||||
|
self._info._X11.XDrawLine(self.displays[i].display, self.displays[i].window_left, self.displays[i].window_left.gc, 0, self.displays[i].bottom / 2, 0, self.displays[i].bottom);
|
||||||
|
self._info._X11.XFlush(self.displays[i].display);
|
||||||
|
}
|
||||||
|
self._timeout = setTimeout(self._isUnity ? self.unity_drawBorder : self.timeoutHandler, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(process.platform)
|
||||||
|
{
|
||||||
|
case 'win32':
|
||||||
|
module.exports = new windows_monitorborder();
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
module.exports = new linux_monitorborder();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
34
agents-new/modules_meshcore/power-monitor.js
Normal file
34
agents-new/modules_meshcore/power-monitor.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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();
|
343
agents-new/modules_meshcore/smbios.js
Normal file
343
agents-new/modules_meshcore/smbios.js
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
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) { }
|
||||||
|
try { Object.defineProperty(String.prototype, "replaceAll", { value: function replaceAll(oldVal, newVal) { return (this.split(oldVal).join(newVal)); } }); } catch (e) { }
|
||||||
|
|
||||||
|
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'];
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
this._native = this._marshal.CreateNativeProxy("Kernel32.dll");
|
||||||
|
|
||||||
|
this._native.CreateMethod('EnumSystemFirmwareTables');
|
||||||
|
this._native.CreateMethod('GetSystemFirmwareTable');
|
||||||
|
}
|
||||||
|
if (process.platform == 'linux') {
|
||||||
|
this._canonicalizeData = function _canonicalizeData(data) {
|
||||||
|
var lines = data.toString().split('Header and Data:\x0A');
|
||||||
|
var MemoryStream = require('MemoryStream');
|
||||||
|
var ms = new MemoryStream();
|
||||||
|
|
||||||
|
for (var i = 1; i < lines.length; ++i) {
|
||||||
|
var tokens = lines[i].split('Strings:\x0A');
|
||||||
|
var header = tokens[0].split('\x0A\x0A')[0].replaceAll('\x0A', '').trim().replaceAll(' ', '').replaceAll('\x09', '');
|
||||||
|
ms.write(Buffer.from(header, 'hex'));
|
||||||
|
if (tokens.length > 1) {
|
||||||
|
var strings = tokens[1].split('\x0A\x0A')[0].split('\x0A');
|
||||||
|
var stringsFinal = [];
|
||||||
|
for (var strx in strings) {
|
||||||
|
var tmp = strings[strx].trim().replaceAll(' ', '').replaceAll('\x09', '');
|
||||||
|
if (!(tmp[0] == '"')) { stringsFinal.push(tmp); }
|
||||||
|
}
|
||||||
|
ms.write(Buffer.from(stringsFinal.join(''), 'hex'));
|
||||||
|
ms.write(Buffer.from('00', 'hex'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ms.write(Buffer.from('0000', 'hex'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var retVal = ms.buffer;
|
||||||
|
retVal.ms = ms;
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this._parse = function _parse(SMData) {
|
||||||
|
var ret = {};
|
||||||
|
var pbyte;
|
||||||
|
var i = 0
|
||||||
|
var SMData;
|
||||||
|
var structcount = 0;
|
||||||
|
|
||||||
|
while (SMData && i < SMData.length)
|
||||||
|
{
|
||||||
|
var SMtype = SMData[i];
|
||||||
|
var SMlength = SMData[i + 1];
|
||||||
|
|
||||||
|
if (!ret[SMtype]) { ret[SMtype] = []; }
|
||||||
|
ret[SMtype].push(SMData.slice(i + 4, i + SMlength));
|
||||||
|
if (process.platform == 'win32') { ret[SMtype].peek()._ext = pbyte; }
|
||||||
|
i += SMlength;
|
||||||
|
|
||||||
|
ret[SMtype].peek()._strings = [];
|
||||||
|
|
||||||
|
while (SMData[i] != 0 && i <= SMData.length)
|
||||||
|
{
|
||||||
|
var strstart = i;
|
||||||
|
|
||||||
|
// Start of String, find end of string
|
||||||
|
while (SMData[i++] != 0 && i <= SMData.length);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ret[SMtype].peek()._strings.push(SMData.slice(strstart, i).toString().trim());
|
||||||
|
}
|
||||||
|
catch (ee)
|
||||||
|
{
|
||||||
|
console.log('oops');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += (ret[SMtype].peek()._strings.length == 0) ? 2 : 1;
|
||||||
|
++structcount;
|
||||||
|
//console.log('End of Table[' + SMtype + ']: ' + i);
|
||||||
|
}
|
||||||
|
//console.log('Struct Count = ' + structcount);
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
this.get = function get(callback) {
|
||||||
|
if (process.platform == 'win32') {
|
||||||
|
var size = this._native.GetSystemFirmwareTable(RSMB, 0, 0, 0).Val;
|
||||||
|
//console.log('Table Size: ' + size);
|
||||||
|
|
||||||
|
var PtrSize = this._marshal.CreatePointer()._size;
|
||||||
|
var buffer = this._marshal.CreateVariable(size);
|
||||||
|
var written = this._native.GetSystemFirmwareTable(RSMB, 0, buffer, size).Val;
|
||||||
|
//console.log('Written Size: ' + written);
|
||||||
|
|
||||||
|
var rawBuffer = buffer.toBuffer();
|
||||||
|
var length = buffer.Deref(4, 4).toBuffer().readUInt32LE(0);
|
||||||
|
|
||||||
|
pbyte = buffer.Deref(8, length);
|
||||||
|
SMData = pbyte.toBuffer();
|
||||||
|
|
||||||
|
if (callback) { callback.apply(this, [this._parse(SMData)]); return; } else { return (this._parse(SMData)); }
|
||||||
|
}
|
||||||
|
if (process.platform == 'linux') {
|
||||||
|
var MemoryStream = require('MemoryStream');
|
||||||
|
this.child = require('child_process').execFile('/usr/sbin/dmidecode', ['dmidecode', '-u']);
|
||||||
|
this.child.SMBiosTable = this;
|
||||||
|
this.child.ms = new MemoryStream();
|
||||||
|
this.child.ms.callback = callback;
|
||||||
|
this.child.ms.child = this.child;
|
||||||
|
this.child.stdout.on('data', function (buffer) { this.parent.ms.write(buffer); });
|
||||||
|
this.child.on('exit', function () { this.ms.end(); });
|
||||||
|
this.child.ms.on('end', function () {
|
||||||
|
//console.log('read ' + this.buffer.length + ' bytes');
|
||||||
|
if (this.buffer.length < 300) {
|
||||||
|
//console.log('Not enough permission to read SMBiosTable');
|
||||||
|
if (this.callback) { this.callback.apply(this.child.SMBiosTable, []); }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var SMData = this.child.SMBiosTable._canonicalizeData(this.buffer);
|
||||||
|
var j = this.child.SMBiosTable._parse(SMData);
|
||||||
|
if (this.callback) { this.callback.apply(this.child.SMBiosTable, [j]); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (callback) { callback.apply(this, [null]); return; } else { return (null); }
|
||||||
|
};
|
||||||
|
this.parse = function parse(data) {
|
||||||
|
var r = {};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.processorInfo = this.processorInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.memoryInfo = this.memoryInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.systemInfo = this.systemInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.systemSlots = this.systemInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r.amtInfo = this.amtInfo(data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
this.processorInfo = function processorInfo(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var ret = [];
|
||||||
|
var ptype = ['ERROR', 'Other', 'Unknown', 'CPU', 'ALU', 'DSP', 'GPU'];
|
||||||
|
var statusString = ['Unknown', 'Enabled', 'Disabled by user', 'Disabled by BIOS', 'Idle', 'Reserved', 'Reserved', 'Other'];
|
||||||
|
var cpuid = 0;
|
||||||
|
while (data[4] && data[4].length > 0) {
|
||||||
|
var p = data[4].pop();
|
||||||
|
var populated = p[20] & 0x40;
|
||||||
|
var status = p[20] & 0x07
|
||||||
|
if (populated) {
|
||||||
|
var j = { _ObjectID: 'SMBiosTables.processorInfo' };
|
||||||
|
j.Processor = ptype[p[1]];
|
||||||
|
j.MaxSpeed = p.readUInt16LE(16) + ' Mhz';
|
||||||
|
if (p[31]) { j.Cores = p[31]; }
|
||||||
|
if (p[33]) { j.Threads = p[33]; }
|
||||||
|
j.Populated = 1;
|
||||||
|
j.Status = statusString[status];
|
||||||
|
j.Socket = p._strings[p[0] - 1];
|
||||||
|
j.Manufacturer = p._strings[p[3] - 1];
|
||||||
|
j.Version = p._strings[p[12] - 1];
|
||||||
|
ret.push(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
this.memoryInfo = function memoryInfo(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = { _ObjectID: 'SMBiosTables.memoryInfo' };
|
||||||
|
if (data[16]) {
|
||||||
|
var m = data[16].peek();
|
||||||
|
retVal.location = memoryLocation[m[0]];
|
||||||
|
if ((retVal.maxCapacityKb = m.readUInt32LE(3)) == 0x80000000) {
|
||||||
|
retVal.maxCapacityKb = 'A really big number';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.systemInfo = function systemInfo(data)
|
||||||
|
{
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = { _ObjectID: 'SMBiosTables.systemInfo' };
|
||||||
|
if (data[1])
|
||||||
|
{
|
||||||
|
var si = data[1].peek();
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
this.systemSlots = function systemSlots(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = [];
|
||||||
|
if (data[9]) {
|
||||||
|
while (data[9].length > 0) {
|
||||||
|
var ss = data[9].pop();
|
||||||
|
retVal.push({ name: ss._strings[ss[0] - 1] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.amtInfo = function amtInfo(data) {
|
||||||
|
if (!data) { throw ('no data'); }
|
||||||
|
var retVal = { AMT: false };
|
||||||
|
if (data[130] && data[130].peek().slice(0, 4).toString() == '$AMT') {
|
||||||
|
var amt = data[130].peek();
|
||||||
|
retVal.AMT = amt[4] ? true : false;
|
||||||
|
if (retVal.AMT) {
|
||||||
|
retVal.enabled = amt[5] ? true : false;
|
||||||
|
retVal.storageRedirection = amt[6] ? true : false;
|
||||||
|
retVal.serialOverLan = amt[7] ? true : false;
|
||||||
|
retVal.kvm = amt[14] ? true : false;
|
||||||
|
if (data[131].peek() && data[131].peek().slice(52, 56).toString() == 'vPro') {
|
||||||
|
var settings = data[131].peek();
|
||||||
|
if (settings[0] & 0x04) { retVal.TXT = (settings[0] & 0x08) ? true : false; }
|
||||||
|
if (settings[0] & 0x10) { retVal.VMX = (settings[0] & 0x20) ? true : false; }
|
||||||
|
retVal.MEBX = settings.readUInt16LE(10).toString() + '.' + settings.readUInt16LE(8).toString() + '.' + settings.readUInt16LE(6).toString() + '.' + settings.readUInt16LE(4).toString();
|
||||||
|
|
||||||
|
var mecap = settings.slice(20, 32);
|
||||||
|
retVal.ManagementEngine = mecap.readUInt16LE(6).toString() + '.' + mecap.readUInt16LE(4).toString() + '.' + mecap.readUInt16LE(2).toString() + '.' + mecap.readUInt16LE(0).toString();
|
||||||
|
|
||||||
|
//var lan = settings.slice(36, 48);
|
||||||
|
//console.log(lan.toString('hex'));
|
||||||
|
//retVal.LAN = (lan.readUInt16LE(10) & 0x03).toString() + '/' + ((lan.readUInt16LE(10) & 0xF8) >> 3).toString();
|
||||||
|
|
||||||
|
//console.log(lan.readUInt16LE(3));
|
||||||
|
//retVal.WLAN = (lan.readUInt16LE(3) & 0x07).toString() + '/' + ((lan.readUInt16LE(3) & 0xF8) >> 3).toString() + '/' + (lan.readUInt16LE(3) >> 8).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.smTableTypes = {
|
||||||
|
0: 'BIOS information',
|
||||||
|
1: 'System information',
|
||||||
|
2: 'Baseboard (or Module) information',
|
||||||
|
4: 'Processor information',
|
||||||
|
5: 'memory controller information',
|
||||||
|
6: 'Memory module information',
|
||||||
|
7: 'Cache information',
|
||||||
|
8: 'Port connector information',
|
||||||
|
9: 'System slots',
|
||||||
|
10: 'On board devices information',
|
||||||
|
11: 'OEM strings',
|
||||||
|
12: 'System configuration options',
|
||||||
|
13: 'BIOS language information',
|
||||||
|
14: 'Group associations',
|
||||||
|
15: 'System event log',
|
||||||
|
16: 'Physical memory array',
|
||||||
|
17: 'Memory device',
|
||||||
|
18: '32bit memory error information',
|
||||||
|
19: 'Memory array mapped address',
|
||||||
|
20: 'Memory device mapped address',
|
||||||
|
21: 'Built-in pointing device',
|
||||||
|
22: 'Portable battery',
|
||||||
|
23: 'System reset',
|
||||||
|
24: 'Hardware security',
|
||||||
|
25: 'System power controls',
|
||||||
|
26: 'Voltage probe',
|
||||||
|
27: 'Cooling device',
|
||||||
|
28: 'Temperature probe',
|
||||||
|
29: 'Electrical current probe',
|
||||||
|
30: 'Out-of-band remote access',
|
||||||
|
31: 'Boot integrity services (BIS) entry point',
|
||||||
|
32: 'System boot information',
|
||||||
|
33: '64bit memory error information',
|
||||||
|
34: 'Management device',
|
||||||
|
35: 'Management device component',
|
||||||
|
36: 'Management device threshold data',
|
||||||
|
37: 'Memory channel',
|
||||||
|
38: 'IPMI device information',
|
||||||
|
39: 'System power supply',
|
||||||
|
40: 'Additional information',
|
||||||
|
41: 'Onboard devices extended information',
|
||||||
|
42: 'Management controller host interface',
|
||||||
|
126: 'Inactive',
|
||||||
|
127: 'End-of-table'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new SMBiosTables();
|
125
agents-new/modules_meshcore/toaster.js
Normal file
125
agents-new/modules_meshcore/toaster.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var toasters = {};
|
||||||
|
|
||||||
|
function Toaster()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'toaster';
|
||||||
|
this.Toast = function Toast(title, caption)
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
var emitter = require('events').inherits(retVal);
|
||||||
|
emitter.createEvent('Dismissed');
|
||||||
|
|
||||||
|
retVal.title = title;
|
||||||
|
retVal.caption = caption;
|
||||||
|
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
emitter.createEvent('Clicked');
|
||||||
|
|
||||||
|
var session = require('user-sessions').Current();
|
||||||
|
for (var i in session) {
|
||||||
|
console.log(session[i]);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log('Attempting Toast Mechanism 1');
|
||||||
|
retVal._child = require('ScriptContainer').Create({ processIsolation: true, sessionId: session.Active[0].SessionId });
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
console.log('Attempting Toast Mechanism 2');
|
||||||
|
retVal._child = require('ScriptContainer').Create({ processIsolation: true });
|
||||||
|
}
|
||||||
|
retVal._child.parent = retVal;
|
||||||
|
|
||||||
|
retVal._child.on('exit', function (code) { this.parent.emit('Dismissed'); delete this.parent._child; });
|
||||||
|
retVal._child.addModule('win-console', getJSModule('win-console'));
|
||||||
|
retVal._child.addModule('win-message-pump', getJSModule('win-message-pump'));
|
||||||
|
|
||||||
|
var str = "\
|
||||||
|
try{\
|
||||||
|
var toast = require('win-console');\
|
||||||
|
var balloon = toast.SetTrayIcon({ szInfo: '" + caption + "', szInfoTitle: '" + title + "', balloonOnly: true });\
|
||||||
|
balloon.on('ToastDismissed', function(){process.exit();});\
|
||||||
|
}\
|
||||||
|
catch(e)\
|
||||||
|
{\
|
||||||
|
require('ScriptContainer').send(e);\
|
||||||
|
}\
|
||||||
|
require('ScriptContainer').send('done');\
|
||||||
|
";
|
||||||
|
retVal._child.ExecuteString(str);
|
||||||
|
toasters[retVal._hashCode()] = retVal;
|
||||||
|
retVal.on('Dismissed', function () { delete toasters[this._hashCode()]; });
|
||||||
|
console.log('Returning');
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!require('fs').existsSync('/usr/bin/notify-send'))
|
||||||
|
{
|
||||||
|
throw ('Toast not supported on this platform');
|
||||||
|
}
|
||||||
|
Object.defineProperty(retVal, '_sessions', {
|
||||||
|
value: require('user-sessions').Current(function onCurrentSession(sessions)
|
||||||
|
{
|
||||||
|
this._cchild = require('child_process').execFile('/usr/bin/whoami', ['whoami'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._cchild.stdout.on('data', function (chunk)
|
||||||
|
{
|
||||||
|
if (chunk.toString().split('\r\n')[0] == 'root')
|
||||||
|
{
|
||||||
|
if (sessions[':0'].State != 'Connected' && sessions[':0'].State != 'Active')
|
||||||
|
{
|
||||||
|
// No logged in user owns the display
|
||||||
|
this.parent.parent.Parent.emit('Dismissed');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We root, so we need to direct to DISPLAY=:0
|
||||||
|
this.parent.parent._notify = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this.parent.parent._notify.stdin.write('su - ' + sessions[':0'].Username + ' -c "DISPLAY=:0 notify-send \'' + this.parent.parent.Parent.title + '\' \'' + this.parent.parent.Parent.caption + '\'"\n');
|
||||||
|
this.parent.parent._notify.stdin.write('exit\n');
|
||||||
|
this.parent.parent._notify.stdout.on('data', function (chunk) { });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We ain't root, so that means we can just call send-notify directly
|
||||||
|
this.parent.parent._notify = require('child_process').execFile('/usr/bin/notify-send', ['notify-send', this.parent.parent.Parent.title, this.parent.parent.Parent.caption], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this.parent.parent._notify.stdout.on('data', function (chunk) { });
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTIFY-SEND has a bug where timeouts don't work, so the default is 10 seconds
|
||||||
|
this.parent.parent.Parent._timeout = setTimeout(function onFakeDismissed(obj)
|
||||||
|
{
|
||||||
|
obj.emit('Dismissed');
|
||||||
|
}, 10000, this.parent.parent.Parent);
|
||||||
|
});
|
||||||
|
this._cchild.parent = this;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
retVal._sessions.Parent = retVal;
|
||||||
|
|
||||||
|
toasters[retVal._hashCode()] = retVal;
|
||||||
|
retVal.on('Dismissed', function () { delete toasters[this._hashCode()]; });
|
||||||
|
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new Toaster();
|
170
agents-new/modules_meshcore/wifi-scanner-windows.js
Normal file
170
agents-new/modules_meshcore/wifi-scanner-windows.js
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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 _Scan()
|
||||||
|
{
|
||||||
|
var wlanInterfaces = this.Marshal.CreatePointer();
|
||||||
|
this.Native.WlanEnumInterfaces(this.Handle, 0, wlanInterfaces);
|
||||||
|
|
||||||
|
var count = wlanInterfaces.Deref().Deref(0, 4).toBuffer().readUInt32LE(0);
|
||||||
|
|
||||||
|
var info = wlanInterfaces.Deref().Deref(8, 532);
|
||||||
|
var iname = info.Deref(16, 512).AnsiString;
|
||||||
|
|
||||||
|
var istate;
|
||||||
|
switch (info.Deref(528, 4).toBuffer().readUInt32LE(0))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
istate = "NOT READY";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
istate = "CONNECTED";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
istate = "AD-HOC";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
istate = "DISCONNECTING";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
istate = "DISCONNECTED";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
istate = "ASSOCIATING";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
istate = "DISCOVERING";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
istate = "AUTHENTICATING";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
istate = "UNKNOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var iguid = info.Deref(0, 16);
|
||||||
|
if (this.Native.WlanScan(this.Handle, iguid, 0, 0, 0).Val == 0)
|
||||||
|
{
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccessPoint(_ssid, _bssid, _rssi, _lq)
|
||||||
|
{
|
||||||
|
this.ssid = _ssid;
|
||||||
|
this.bssid = _bssid;
|
||||||
|
this.rssi = _rssi;
|
||||||
|
this.lq = _lq;
|
||||||
|
}
|
||||||
|
AccessPoint.prototype.toString = function()
|
||||||
|
{
|
||||||
|
return (this.ssid + " [" + this.bssid + "]: " + this.lq);
|
||||||
|
}
|
||||||
|
|
||||||
|
function OnNotify(NotificationData)
|
||||||
|
{
|
||||||
|
var NotificationSource = NotificationData.Deref(0, 4).toBuffer().readUInt32LE(0);
|
||||||
|
var NotificationCode = NotificationData.Deref(4, 4).toBuffer().readUInt32LE(0);
|
||||||
|
var dataGuid = NotificationData.Deref(8, 16);
|
||||||
|
|
||||||
|
if ((NotificationSource & 0X00000008) && (NotificationCode == 7))
|
||||||
|
{
|
||||||
|
var bss = this.Parent.Marshal.CreatePointer();
|
||||||
|
var result = this.Parent.Native.GetBSSList(this.Parent.Handle, dataGuid, 0, 3, 0, 0, bss).Val;
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
var totalSize = bss.Deref().Deref(0, 4).toBuffer().readUInt32LE(0);
|
||||||
|
var numItems = bss.Deref().Deref(4, 4).toBuffer().readUInt32LE(0);
|
||||||
|
for (i = 0; i < numItems; ++i)
|
||||||
|
{
|
||||||
|
var item = bss.Deref().Deref(8 + (360 * i), 360);
|
||||||
|
var ssid = item.Deref(4, 32).String.trim();
|
||||||
|
var bssid = item.Deref(40, 6).HexString2;
|
||||||
|
var rssi = item.Deref(56, 4).toBuffer().readUInt32LE(0);
|
||||||
|
var lq = item.Deref(60, 4).toBuffer().readUInt32LE(0);
|
||||||
|
|
||||||
|
this.Parent.emit('Scan', new AccessPoint(ssid, bssid, rssi, lq));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Wireless()
|
||||||
|
{
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
|
||||||
|
this.Marshal = require('_GenericMarshal');
|
||||||
|
this.Native = this.Marshal.CreateNativeProxy("wlanapi.dll");
|
||||||
|
this.Native.CreateMethod("WlanOpenHandle");
|
||||||
|
this.Native.CreateMethod("WlanGetNetworkBssList", "GetBSSList");
|
||||||
|
this.Native.CreateMethod("WlanRegisterNotification");
|
||||||
|
this.Native.CreateMethod("WlanEnumInterfaces");
|
||||||
|
this.Native.CreateMethod("WlanScan");
|
||||||
|
this.Native.CreateMethod("WlanQueryInterface");
|
||||||
|
|
||||||
|
var negotiated = this.Marshal.CreatePointer();
|
||||||
|
var h = this.Marshal.CreatePointer();
|
||||||
|
|
||||||
|
this.Native.WlanOpenHandle(2, 0, negotiated, h);
|
||||||
|
this.Handle = h.Deref();
|
||||||
|
|
||||||
|
this._NOTIFY_PROXY_OBJECT = this.Marshal.CreateCallbackProxy(OnNotify, 2);
|
||||||
|
this._NOTIFY_PROXY_OBJECT.Parent = this;
|
||||||
|
var PrevSource = this.Marshal.CreatePointer();
|
||||||
|
var result = this.Native.WlanRegisterNotification(this.Handle, 0X0000FFFF, 0, this._NOTIFY_PROXY_OBJECT.Callback, this._NOTIFY_PROXY_OBJECT.State, 0, PrevSource);
|
||||||
|
|
||||||
|
emitterUtils.createEvent('Scan');
|
||||||
|
emitterUtils.addMethod('Scan', _Scan);
|
||||||
|
|
||||||
|
this.GetConnectedNetwork = function ()
|
||||||
|
{
|
||||||
|
var interfaces = this.Marshal.CreatePointer();
|
||||||
|
|
||||||
|
console.log('Success = ' + this.Native.WlanEnumInterfaces(this.Handle, 0, interfaces).Val);
|
||||||
|
var count = interfaces.Deref().Deref(0, 4).toBuffer().readUInt32LE(0);
|
||||||
|
var info = interfaces.Deref().Deref(8, 532);
|
||||||
|
var iname = info.Deref(16, 512).AnsiString;
|
||||||
|
var istate = info.Deref(528, 4).toBuffer().readUInt32LE(0);
|
||||||
|
if(info.Deref(528, 4).toBuffer().readUInt32LE(0) == 1) // CONNECTED
|
||||||
|
{
|
||||||
|
var dataSize = this.Marshal.CreatePointer();
|
||||||
|
var pData = this.Marshal.CreatePointer();
|
||||||
|
var valueType = this.Marshal.CreatePointer();
|
||||||
|
var iguid = info.Deref(0, 16);
|
||||||
|
var retVal = this.Native.WlanQueryInterface(this.Handle, iguid, 7, 0, dataSize, pData, valueType).Val;
|
||||||
|
if (retVal == 0)
|
||||||
|
{
|
||||||
|
var associatedSSID = pData.Deref().Deref(524, 32).String;
|
||||||
|
var bssid = pData.Deref().Deref(560, 6).HexString;
|
||||||
|
var lq = pData.Deref().Deref(576, 4).toBuffer().readUInt32LE(0);
|
||||||
|
|
||||||
|
return (new AccessPoint(associatedSSID, bssid, 0, lq));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw ("GetConnectedNetworks: FAILED (not associated to a network)");
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new Wireless();
|
127
agents-new/modules_meshcore/wifi-scanner.js
Normal file
127
agents-new/modules_meshcore/wifi-scanner.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var MemoryStream = require('MemoryStream');
|
||||||
|
var WindowsChildScript = 'var parent = require("ScriptContainer");var Wireless = require("wifi-scanner-windows");Wireless.on("Scan", function (ap) { parent.send(ap); });Wireless.Scan();';
|
||||||
|
|
||||||
|
|
||||||
|
function AccessPoint(_ssid, _bssid, _lq)
|
||||||
|
{
|
||||||
|
this.ssid = _ssid;
|
||||||
|
this.bssid = _bssid;
|
||||||
|
this.lq = _lq;
|
||||||
|
}
|
||||||
|
AccessPoint.prototype.toString = function ()
|
||||||
|
{
|
||||||
|
return ("[" + this.bssid + "]: " + this.ssid + " (" + this.lq + ")");
|
||||||
|
//return (this.ssid + " [" + this.bssid + "]: " + this.lq);
|
||||||
|
}
|
||||||
|
|
||||||
|
function WiFiScanner()
|
||||||
|
{
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('accessPoint');
|
||||||
|
|
||||||
|
this.hasWireless = function ()
|
||||||
|
{
|
||||||
|
var retVal = false;
|
||||||
|
var interfaces = require('os').networkInterfaces();
|
||||||
|
for (var name in interfaces)
|
||||||
|
{
|
||||||
|
if (interfaces[name][0].type == 'wireless') { retVal = true; break; }
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Scan = function ()
|
||||||
|
{
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this.master = require('ScriptContainer').Create(15, ContainerPermissions.DEFAULT);
|
||||||
|
this.master.parent = this;
|
||||||
|
this.master.on('data', function (j) { this.parent.emit('accessPoint', new AccessPoint(j.ssid, j.bssid, j.lq)); });
|
||||||
|
|
||||||
|
this.master.addModule('wifi-scanner-windows', getJSModule('wifi-scanner-windows'));
|
||||||
|
this.master.ExecuteString(WindowsChildScript);
|
||||||
|
}
|
||||||
|
else if (process.platform == 'linux')
|
||||||
|
{
|
||||||
|
// Need to get the wireless interface name
|
||||||
|
var interfaces = require('os').networkInterfaces();
|
||||||
|
var wlan = null;
|
||||||
|
for (var i in interfaces)
|
||||||
|
{
|
||||||
|
if (interfaces[i][0].type == 'wireless')
|
||||||
|
{
|
||||||
|
wlan = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wlan != null)
|
||||||
|
{
|
||||||
|
this.child = require('child_process').execFile('/sbin/iwlist', ['iwlist', wlan, 'scan']);
|
||||||
|
this.child.parent = this;
|
||||||
|
this.child.ms = new MemoryStream();
|
||||||
|
this.child.ms.parent = this.child;
|
||||||
|
this.child.stdout.on('data', function (buffer) { this.parent.ms.write(buffer); });
|
||||||
|
this.child.on('exit', function () { this.ms.end(); });
|
||||||
|
this.child.ms.on('end', function ()
|
||||||
|
{
|
||||||
|
var str = this.buffer.toString();
|
||||||
|
tokens = str.split(' - Address: ');
|
||||||
|
for (var block in tokens)
|
||||||
|
{
|
||||||
|
if (block == 0) continue;
|
||||||
|
var ln = tokens[block].split('\n');
|
||||||
|
var _bssid = ln[0];
|
||||||
|
var _lq;
|
||||||
|
var _ssid;
|
||||||
|
|
||||||
|
for (var lnblock in ln)
|
||||||
|
{
|
||||||
|
lnblock = ln[lnblock].trim();
|
||||||
|
lnblock = lnblock.trim();
|
||||||
|
if (lnblock.startsWith('ESSID:'))
|
||||||
|
{
|
||||||
|
_ssid = lnblock.slice(7, lnblock.length - 1);
|
||||||
|
if (_ssid == '<hidden>') { _ssid = ''; }
|
||||||
|
}
|
||||||
|
if (lnblock.startsWith('Signal level='))
|
||||||
|
{
|
||||||
|
_lq = lnblock.slice(13,lnblock.length-4);
|
||||||
|
}
|
||||||
|
else if (lnblock.startsWith('Quality='))
|
||||||
|
{
|
||||||
|
_lq = lnblock.slice(8, 10);
|
||||||
|
var scale = lnblock.slice(11, 13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.parent.parent.emit('accessPoint', new AccessPoint(_ssid, _bssid, _lq));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WiFiScanner;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
164
agents-new/modules_meshcore/win-console.js
Normal file
164
agents-new/modules_meshcore/win-console.js
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var TrayIconFlags =
|
||||||
|
{
|
||||||
|
NIF_MESSAGE: 0x00000001,
|
||||||
|
NIF_ICON: 0x00000002,
|
||||||
|
NIF_TIP: 0x00000004,
|
||||||
|
NIF_STATE: 0x00000008,
|
||||||
|
NIF_INFO: 0x00000010,
|
||||||
|
NIF_GUID: 0x00000020,
|
||||||
|
NIF_REALTIME: 0x00000040,
|
||||||
|
NIF_SHOWTIP: 0x00000080,
|
||||||
|
|
||||||
|
NIM_ADD: 0x00000000,
|
||||||
|
NIM_MODIFY: 0x00000001,
|
||||||
|
NIM_DELETE: 0x00000002,
|
||||||
|
NIM_SETFOCUS: 0x00000003,
|
||||||
|
NIM_SETVERSION: 0x00000004
|
||||||
|
};
|
||||||
|
var NOTIFYICON_VERSION_4 = 4;
|
||||||
|
var MessageTypes = { WM_APP: 0x8000, WM_USER: 0x0400 };
|
||||||
|
function WindowsConsole()
|
||||||
|
{
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this._ObjectID = 'win-console';
|
||||||
|
this._Marshal = require('_GenericMarshal');
|
||||||
|
this._kernel32 = this._Marshal.CreateNativeProxy("kernel32.dll");
|
||||||
|
this._user32 = this._Marshal.CreateNativeProxy("user32.dll");
|
||||||
|
this._kernel32.CreateMethod("GetConsoleWindow");
|
||||||
|
this._kernel32.CreateMethod('GetCurrentThread');
|
||||||
|
this._user32.CreateMethod("ShowWindow");
|
||||||
|
this._user32.CreateMethod("LoadImageA");
|
||||||
|
this._user32.CreateMethod({ method: 'GetMessageA', threadDispatch: 1 });
|
||||||
|
this._shell32 = this._Marshal.CreateNativeProxy('Shell32.dll');
|
||||||
|
this._shell32.CreateMethod('Shell_NotifyIconA');
|
||||||
|
|
||||||
|
this._handle = this._kernel32.GetConsoleWindow();
|
||||||
|
this.minimize = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 6);
|
||||||
|
};
|
||||||
|
this.restore = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 9);
|
||||||
|
};
|
||||||
|
this.hide = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 0);
|
||||||
|
};
|
||||||
|
this.show = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 5);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this._loadicon = function (imagePath) {
|
||||||
|
var h = this._user32.LoadImageA(0, this._Marshal.CreateVariable(imagePath), 1, 0, 0, 0x00000010 | 0x00008000 | 0x00000040); // LR_LOADFROMFILE | LR_SHARED | LR_DEFAULTSIZE
|
||||||
|
return (h);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.SetTrayIcon = function SetTrayIcon(options)
|
||||||
|
{
|
||||||
|
var data = this._Marshal.CreateVariable(this._Marshal.PointerSize == 4 ? 508 : 528);
|
||||||
|
//console.log('struct size = ' + data._size);
|
||||||
|
//console.log('TryIcon, WM_MESSAGE filter = ' + options.filter);
|
||||||
|
data.toBuffer().writeUInt32LE(data._size, 0);
|
||||||
|
|
||||||
|
var trayType = TrayIconFlags.NIF_TIP | TrayIconFlags.NIF_MESSAGE
|
||||||
|
options.filter = MessageTypes.WM_APP + 1;
|
||||||
|
data.Deref(this._Marshal.PointerSize == 4 ? 16 : 24, 4).toBuffer().writeUInt32LE(options.filter);
|
||||||
|
|
||||||
|
if (!options.noBalloon) { trayType |= TrayIconFlags.NIF_INFO; }
|
||||||
|
|
||||||
|
if (options.icon)
|
||||||
|
{
|
||||||
|
trayType |= TrayIconFlags.NIF_ICON;
|
||||||
|
var hIcon = data.Deref(this._Marshal.PointerSize == 4 ? 20 : 32, this._Marshal.PointerSize);
|
||||||
|
options.icon.pointerBuffer().copy(hIcon.toBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Deref(this._Marshal.PointerSize * 2, 4).toBuffer().writeUInt32LE(1);
|
||||||
|
data.Deref(this._Marshal.PointerSize == 4 ? 12 : 20, 4).toBuffer().writeUInt32LE(trayType);
|
||||||
|
data.Deref(this._Marshal.PointerSize == 4 ? 416 : 432, 4).toBuffer().writeUInt32LE(NOTIFYICON_VERSION_4);
|
||||||
|
|
||||||
|
var szTip = data.Deref(this._Marshal.PointerSize == 4 ? 24 : 40, 128);
|
||||||
|
var szInfo = data.Deref(this._Marshal.PointerSize == 4 ? 160 : 176, 256);
|
||||||
|
var szInfoTitle = data.Deref(this._Marshal.PointerSize == 4 ? 420 : 436, 64);
|
||||||
|
|
||||||
|
if (options.szTip) { Buffer.from(options.szTip).copy(szTip.toBuffer()); }
|
||||||
|
if (options.szInfo) { Buffer.from(options.szInfo).copy(szInfo.toBuffer()); }
|
||||||
|
if (options.szInfoTitle) { Buffer.from(options.szInfoTitle).copy(szInfoTitle.toBuffer()); }
|
||||||
|
|
||||||
|
|
||||||
|
var MessagePump = require('win-message-pump');
|
||||||
|
retVal = { _ObjectID: 'WindowsConsole.TrayIcon', MessagePump: new MessagePump(options) };
|
||||||
|
var retValEvents = require('events').inherits(retVal);
|
||||||
|
retValEvents.createEvent('ToastClicked');
|
||||||
|
retValEvents.createEvent('IconHover');
|
||||||
|
retValEvents.createEvent('ToastDismissed');
|
||||||
|
retVal.Options = options;
|
||||||
|
retVal.MessagePump.TrayIcon = retVal;
|
||||||
|
retVal.MessagePump.NotifyData = data;
|
||||||
|
retVal.MessagePump.WindowsConsole = this;
|
||||||
|
retVal.MessagePump.on('exit', function onExit(code) { console.log('Pump Exited'); if (this.TrayIcon) { this.TrayIcon.remove(); } });
|
||||||
|
retVal.MessagePump.on('hwnd', function onHwnd(h)
|
||||||
|
{
|
||||||
|
//console.log('Got HWND');
|
||||||
|
options.hwnd = h;
|
||||||
|
h.pointerBuffer().copy(this.NotifyData.Deref(this.WindowsConsole._Marshal.PointerSize, this.WindowsConsole._Marshal.PointerSize).toBuffer());
|
||||||
|
|
||||||
|
if(this.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_ADD, this.NotifyData).Val == 0)
|
||||||
|
{
|
||||||
|
// Something went wrong
|
||||||
|
}
|
||||||
|
});
|
||||||
|
retVal.MessagePump.on('message', function onWindowsMessage(msg)
|
||||||
|
{
|
||||||
|
if(msg.message == this.TrayIcon.Options.filter)
|
||||||
|
{
|
||||||
|
var handled = false;
|
||||||
|
if (msg.wparam == 1 && msg.lparam == 1029)
|
||||||
|
{
|
||||||
|
this.TrayIcon.emit('ToastClicked');
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (msg.wparam == 1 && msg.lparam == 512)
|
||||||
|
{
|
||||||
|
this.TrayIcon.emit('IconHover');
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (this.TrayIcon.Options.balloonOnly && msg.wparam == 1 && (msg.lparam == 1028 || msg.lparam == 1029))
|
||||||
|
{
|
||||||
|
this.TrayIcon.emit('ToastDismissed');
|
||||||
|
this.TrayIcon.remove();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (!handled) { console.log(msg); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
retVal.remove = function remove()
|
||||||
|
{
|
||||||
|
this.MessagePump.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_DELETE, this.MessagePump.NotifyData);
|
||||||
|
this.MessagePump.stop();
|
||||||
|
delete this.MessagePump.TrayIcon;
|
||||||
|
delete this.MessagePump;
|
||||||
|
};
|
||||||
|
return (retVal);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new WindowsConsole();
|
507
agents-new/modules_meshcore/win-terminal.js
Normal file
507
agents-new/modules_meshcore/win-terminal.js
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var promise = require('promise');
|
||||||
|
var duplex = require('stream').Duplex;
|
||||||
|
|
||||||
|
var SW_HIDE = 0;
|
||||||
|
var SW_MINIMIZE = 6;
|
||||||
|
var STARTF_USESHOWWINDOW = 0x1;
|
||||||
|
var STD_INPUT_HANDLE = -10;
|
||||||
|
var STD_OUTPUT_HANDLE = -11;
|
||||||
|
var EVENT_CONSOLE_CARET = 0x4001;
|
||||||
|
var EVENT_CONSOLE_END_APPLICATION = 0x4007;
|
||||||
|
var WINEVENT_OUTOFCONTEXT = 0x000;
|
||||||
|
var WINEVENT_SKIPOWNPROCESS = 0x0002;
|
||||||
|
var CREATE_NEW_PROCESS_GROUP = 0x200;
|
||||||
|
var EVENT_CONSOLE_UPDATE_REGION = 0x4002;
|
||||||
|
var EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003;
|
||||||
|
var EVENT_CONSOLE_UPDATE_SCROLL = 0x4004;
|
||||||
|
var EVENT_CONSOLE_LAYOUT = 0x4005;
|
||||||
|
var EVENT_CONSOLE_START_APPLICATION = 0x4006;
|
||||||
|
var KEY_EVENT = 0x1;
|
||||||
|
var MAPVK_VK_TO_VSC = 0;
|
||||||
|
var WM_QUIT = 0x12;
|
||||||
|
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
var si = GM.CreateVariable(GM.PointerSize == 4 ? 68 : 104);
|
||||||
|
var pi = GM.CreateVariable(GM.PointerSize == 4 ? 16 : 24);
|
||||||
|
|
||||||
|
si.Deref(0, 4).toBuffer().writeUInt32LE(GM.PointerSize == 4 ? 68 : 104); // si.cb
|
||||||
|
si.Deref(GM.PointerSize == 4 ? 48 : 64, 2).toBuffer().writeUInt16LE(SW_HIDE | SW_MINIMIZE); // si.wShowWindow
|
||||||
|
si.Deref(GM.PointerSize == 4 ? 44 : 60, 4).toBuffer().writeUInt32LE(STARTF_USESHOWWINDOW); // si.dwFlags;
|
||||||
|
|
||||||
|
var MSG = GM.CreateVariable(GM.PointerSize == 4 ? 28 : 48);
|
||||||
|
|
||||||
|
function windows_terminal() {
|
||||||
|
this._ObjectID = 'windows_terminal';
|
||||||
|
this._user32 = GM.CreateNativeProxy('User32.dll');
|
||||||
|
this._user32.CreateMethod('DispatchMessageA');
|
||||||
|
this._user32.CreateMethod('GetMessageA');
|
||||||
|
this._user32.CreateMethod('MapVirtualKeyA');
|
||||||
|
this._user32.CreateMethod('PostThreadMessageA');
|
||||||
|
this._user32.CreateMethod('SetWinEventHook');
|
||||||
|
this._user32.CreateMethod('ShowWindow');
|
||||||
|
this._user32.CreateMethod('TranslateMessage');
|
||||||
|
this._user32.CreateMethod('UnhookWinEvent');
|
||||||
|
this._user32.CreateMethod('VkKeyScanA');
|
||||||
|
this._user32.terminal = this;
|
||||||
|
|
||||||
|
this._kernel32 = GM.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('AllocConsole');
|
||||||
|
this._kernel32.CreateMethod('CreateProcessA');
|
||||||
|
this._kernel32.CreateMethod('CloseHandle');
|
||||||
|
this._kernel32.CreateMethod('FillConsoleOutputAttribute');
|
||||||
|
this._kernel32.CreateMethod('FillConsoleOutputCharacterA');
|
||||||
|
this._kernel32.CreateMethod('GetConsoleScreenBufferInfo');
|
||||||
|
this._kernel32.CreateMethod('GetConsoleWindow');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._kernel32.CreateMethod('GetStdHandle');
|
||||||
|
this._kernel32.CreateMethod('GetThreadId');
|
||||||
|
this._kernel32.CreateMethod('ReadConsoleOutputA');
|
||||||
|
this._kernel32.CreateMethod('SetConsoleCursorPosition');
|
||||||
|
this._kernel32.CreateMethod('SetConsoleScreenBufferSize');
|
||||||
|
this._kernel32.CreateMethod('SetConsoleWindowInfo');
|
||||||
|
this._kernel32.CreateMethod('TerminateProcess');
|
||||||
|
this._kernel32.CreateMethod('WaitForSingleObject');
|
||||||
|
this._kernel32.CreateMethod('WriteConsoleInputA');
|
||||||
|
|
||||||
|
var currentX = 0;
|
||||||
|
var currentY = 0;
|
||||||
|
|
||||||
|
this._scrx = 0;
|
||||||
|
this._scry = 0;
|
||||||
|
|
||||||
|
this.SendCursorUpdate = function () {
|
||||||
|
var newCsbi = GM.CreateVariable(22);
|
||||||
|
|
||||||
|
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, newCsbi).Val == 0) { return; }
|
||||||
|
if (newCsbi.Deref(4, 2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6, 2).toBuffer().readUInt16LE() != this.currentY) {
|
||||||
|
//wchar_t mywbuf[512];
|
||||||
|
//swprintf(mywbuf, 512, TEXT("csbi.dwCursorPosition.X = %d, csbi.dwCursorPosition.Y = %d, newCsbi.dwCursorPosition.X = %d, newCsbi.dwCursorPosition.Y = %d\r\n"), csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, newCsbi.dwCursorPosition.X, newCsbi.dwCursorPosition.Y);
|
||||||
|
//OutputDebugString(mywbuf);
|
||||||
|
|
||||||
|
//m_viewOffset = newCsbi.srWindow.Top;
|
||||||
|
//WriteMoveCursor((SerialAgent *)this->sa, (char)(newCsbi.dwCursorPosition.Y - m_viewOffset), (char)(newCsbi.dwCursorPosition.X - m_viewOffset));
|
||||||
|
//LowStackSendData((SerialAgent *)(this->sa), "", 0);
|
||||||
|
|
||||||
|
this.currentX = newCsbi.Deref(4, 2).toBuffer().readUInt16LE();
|
||||||
|
this.currentY = newCsbi.Deref(6, 2).toBuffer().readUInt16LE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ClearScreen = function () {
|
||||||
|
var CONSOLE_SCREEN_BUFFER_INFO = GM.CreateVariable(22);
|
||||||
|
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
|
||||||
|
|
||||||
|
var coordScreen = GM.CreateVariable(4);
|
||||||
|
var dwConSize = CONSOLE_SCREEN_BUFFER_INFO.Deref(0, 2).toBuffer().readUInt16LE(0) * CONSOLE_SCREEN_BUFFER_INFO.Deref(2, 2).toBuffer().readUInt16LE(0);
|
||||||
|
var cCharsWritten = GM.CreateVariable(4);
|
||||||
|
|
||||||
|
// Fill the entire screen with blanks.
|
||||||
|
if (this._kernel32.FillConsoleOutputCharacterA(this._stdoutput, 32, dwConSize, coordScreen.Deref(0, 4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
|
||||||
|
|
||||||
|
// Get the current text attribute.
|
||||||
|
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
|
||||||
|
|
||||||
|
// Set the buffer's attributes accordingly.
|
||||||
|
if (this._kernel32.FillConsoleOutputAttribute(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO.Deref(8, 2).toBuffer().readUInt16LE(0), dwConSize, coordScreen.Deref(0, 4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
|
||||||
|
|
||||||
|
// Put the cursor at its home coordinates.
|
||||||
|
this._kernel32.SetConsoleCursorPosition(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE());
|
||||||
|
|
||||||
|
// Put the window to top-left.
|
||||||
|
var rect = GM.CreateVariable(8);
|
||||||
|
var srWindow = CONSOLE_SCREEN_BUFFER_INFO.Deref(10, 8).toBuffer();
|
||||||
|
rect.Deref(4, 2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(4) - srWindow.readUInt16LE(0));
|
||||||
|
rect.Deref(6, 2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(6) - srWindow.readUInt16LE(2));
|
||||||
|
|
||||||
|
this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Start = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT)
|
||||||
|
{
|
||||||
|
this.stopping = null;
|
||||||
|
if (this._kernel32.GetConsoleWindow().Val == 0) {
|
||||||
|
if (this._kernel32.AllocConsole().Val == 0) {
|
||||||
|
throw ('AllocConsole failed with: ' + this._kernel32.GetLastError().Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._stdinput = this._kernel32.GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
this._stdoutput = this._kernel32.GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
this._connected = false;
|
||||||
|
var coordScreen = GM.CreateVariable(4);
|
||||||
|
coordScreen.Deref(0, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH);
|
||||||
|
coordScreen.Deref(2, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
var rect = GM.CreateVariable(8);
|
||||||
|
rect.Deref(4, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH - 1);
|
||||||
|
rect.Deref(6, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT - 1);
|
||||||
|
|
||||||
|
if (this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0) {
|
||||||
|
throw ('Failed to set Console Screen Size');
|
||||||
|
}
|
||||||
|
if (this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE()).Val == 0) {
|
||||||
|
throw ('Failed to set Console Buffer Size');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide the console window
|
||||||
|
this._user32.ShowWindow(this._kernel32.GetConsoleWindow().Val, SW_HIDE);
|
||||||
|
|
||||||
|
this.ClearScreen();
|
||||||
|
this._hookThread().then(function () {
|
||||||
|
// Hook Ready
|
||||||
|
this.terminal.StartCommand();
|
||||||
|
}, console.log);
|
||||||
|
this._stream = new duplex({
|
||||||
|
'write': function (chunk, flush) {
|
||||||
|
if (!this.terminal.connected) {
|
||||||
|
//console.log('_write: ' + chunk);
|
||||||
|
if (!this._promise.chunk) {
|
||||||
|
this._promise.chunk = [];
|
||||||
|
}
|
||||||
|
if (typeof (chunk) == 'string') {
|
||||||
|
this._promise.chunk.push(chunk);
|
||||||
|
} else {
|
||||||
|
this._promise.chunk.push(Buffer.alloc(chunk.length));
|
||||||
|
chunk.copy(this._promise.chunk.peek());
|
||||||
|
}
|
||||||
|
this._promise.chunk.peek().flush = flush;
|
||||||
|
this._promise.then(function () {
|
||||||
|
var buf;
|
||||||
|
while (this.chunk.length > 0) {
|
||||||
|
buf = this.chunk.shift();
|
||||||
|
this.terminal._WriteBuffer(buf);
|
||||||
|
buf.flush();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//console.log('writeNOW: ' + chunk);
|
||||||
|
this.terminal._WriteBuffer(chunk);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
return (true);
|
||||||
|
},
|
||||||
|
'final': function (flush) {
|
||||||
|
var p = this.terminal._stop();
|
||||||
|
p.__flush = flush;
|
||||||
|
p.then(function () { this.__flush(); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._stream.terminal = this;
|
||||||
|
this._stream._promise = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||||
|
this._stream._promise.terminal = this;
|
||||||
|
return (this._stream);
|
||||||
|
};
|
||||||
|
this._stop = function () {
|
||||||
|
if (this.stopping) { return (this.stopping); }
|
||||||
|
//console.log('Stopping Terminal...');
|
||||||
|
this._ConsoleWinEventProc.removeAllListeners('GlobalCallback');
|
||||||
|
this.stopping = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||||
|
|
||||||
|
var threadID = this._kernel32.GetThreadId(this._user32.SetWinEventHook.async.thread()).Val;
|
||||||
|
this._user32.PostThreadMessageA(threadID, WM_QUIT, 0, 0);
|
||||||
|
this._stream.emit('end');
|
||||||
|
return (this.stopping);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._hookThread = function () {
|
||||||
|
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||||
|
ret.terminal = this;
|
||||||
|
this._ConsoleWinEventProc = GM.GetGenericGlobalCallback(7);
|
||||||
|
this._ConsoleWinEventProc.terminal = this;
|
||||||
|
var p = this._user32.SetWinEventHook.async(EVENT_CONSOLE_CARET, EVENT_CONSOLE_END_APPLICATION, 0, this._ConsoleWinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||||
|
p.ready = ret;
|
||||||
|
p.terminal = this;
|
||||||
|
p.then(function (hwinEventHook) {
|
||||||
|
if (hwinEventHook.Val == 0) {
|
||||||
|
this.ready._rej('Error calling SetWinEventHook');
|
||||||
|
} else {
|
||||||
|
this.terminal.hwinEventHook = hwinEventHook;
|
||||||
|
this.ready._res();
|
||||||
|
this.terminal._GetMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime) {
|
||||||
|
if (!this.terminal.hwinEventHook || this.terminal.hwinEventHook.Val != hhook.Val) { return; }
|
||||||
|
var buffer = null;
|
||||||
|
|
||||||
|
switch (dwEvent.Val) {
|
||||||
|
case EVENT_CONSOLE_CARET:
|
||||||
|
break;
|
||||||
|
case EVENT_CONSOLE_UPDATE_REGION:
|
||||||
|
if (!this.terminal.connected) {
|
||||||
|
this.terminal.connected = true;
|
||||||
|
this.terminal._stream._promise._res();
|
||||||
|
}
|
||||||
|
if (this.terminal._scrollTimer == null) {
|
||||||
|
buffer = this.terminal._GetScreenBuffer(LOWORD(idObject.Val), HIWORD(idObject.Val), LOWORD(idChild.Val), HIWORD(idChild.Val));
|
||||||
|
//console.log('UPDATE REGION: [Left: ' + LOWORD(idObject.Val) + ' Top: ' + HIWORD(idObject.Val) + ' Right: ' + LOWORD(idChild.Val) + ' Bottom: ' + HIWORD(idChild.Val) + ']');
|
||||||
|
this.terminal._SendDataBuffer(buffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EVENT_CONSOLE_UPDATE_SIMPLE:
|
||||||
|
//console.log('UPDATE SIMPLE: [X: ' + LOWORD(idObject.Val) + ' Y: ' + HIWORD(idObject.Val) + ' Char: ' + LOWORD(idChild.Val) + ' Attr: ' + HIWORD(idChild.Val) + ']');
|
||||||
|
var simplebuffer = { data: [ Buffer.alloc(1, LOWORD(idChild.Val)) ], attributes: [ HIWORD(idChild.Val) ], width: 1, height: 1, x: LOWORD(idObject.Val), y: HIWORD(idObject.Val) };
|
||||||
|
this.terminal._SendDataBuffer(simplebuffer);
|
||||||
|
break;
|
||||||
|
case EVENT_CONSOLE_UPDATE_SCROLL:
|
||||||
|
//console.log('UPDATE SCROLL: [dx: ' + idObject.Val + ' dy: ' + idChild.Val + ']');
|
||||||
|
this.terminal._SendScroll(idObject.Val, idChild.Val);
|
||||||
|
break;
|
||||||
|
case EVENT_CONSOLE_LAYOUT:
|
||||||
|
//console.log('CONSOLE_LAYOUT');
|
||||||
|
//snprintf( Buf, 512, "Event Console LAYOUT!\r\n");
|
||||||
|
//SendLayout();
|
||||||
|
break;
|
||||||
|
case EVENT_CONSOLE_START_APPLICATION:
|
||||||
|
//console.log('START APPLICATION: [PID: ' + idObject.Val + ' CID: ' + idChild.Val + ']');
|
||||||
|
//snprintf( Buf, 512, "Event Console START APPLICATION!\r\nProcess ID: %d - Child ID: %d\r\n\r\n", (int)idObject, (int)idChild);
|
||||||
|
//SendConsoleEvent(dwEvent, idObject, idChild);
|
||||||
|
break;
|
||||||
|
case EVENT_CONSOLE_END_APPLICATION:
|
||||||
|
if (idObject.Val == this.terminal._hProcessID)
|
||||||
|
{
|
||||||
|
//console.log('END APPLICATION: [PID: ' + idObject.Val + ' CID: ' + idChild.Val + ']');
|
||||||
|
this.terminal._hProcess = null;
|
||||||
|
this.terminal._stop().then(function () { console.log('STOPPED'); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//snprintf(Buf, 512, "unknown console event.\r\n");
|
||||||
|
console.log('Unknown event: ' + dwEvent.Val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//mbstowcs_s(&l, wBuf, Buf, 512);
|
||||||
|
//OutputDebugString(wBuf);
|
||||||
|
|
||||||
|
});
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._GetMessage = function () {
|
||||||
|
if (this._user32.abort) { console.log('aborting loop'); return; }
|
||||||
|
this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret) {
|
||||||
|
//console.log('GetMessage Response');
|
||||||
|
if (ret.Val != 0) {
|
||||||
|
if (ret.Val == -1) {
|
||||||
|
// handle the error and possibly exit
|
||||||
|
} else {
|
||||||
|
//console.log('TranslateMessage');
|
||||||
|
this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
|
||||||
|
//console.log('DispatchMessage');
|
||||||
|
this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
|
||||||
|
this.nativeProxy.terminal._GetMessage();
|
||||||
|
}, console.log);
|
||||||
|
}, console.log);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
this.nativeProxy.UnhookWinEvent.async(this.nativeProxy.terminal._user32.SetWinEventHook.async, this.nativeProxy.terminal.hwinEventHook)
|
||||||
|
.then(function ()
|
||||||
|
{
|
||||||
|
if (this.nativeProxy.terminal._hProcess == null) { return; }
|
||||||
|
|
||||||
|
this.nativeProxy.terminal.stopping._res();
|
||||||
|
if (this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0) {
|
||||||
|
var e = this.nativeProxy.terminal._kernel32.GetLastError().Val;
|
||||||
|
console.log('Unable to kill Terminal Process, error: ' + e);
|
||||||
|
}
|
||||||
|
this.nativeProxy.terminal.stopping = null;
|
||||||
|
}, function (err)
|
||||||
|
{
|
||||||
|
console.log('REJECTED_UnhookWinEvent: ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function (err) {
|
||||||
|
// Get Message Failed
|
||||||
|
console.log('REJECTED_GETMessage: ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._WriteBuffer = function (buf) {
|
||||||
|
for (var i = 0; i < buf.length; ++i) {
|
||||||
|
if (typeof (buf) == 'string') {
|
||||||
|
this._WriteCharacter(buf.charCodeAt(i), false);
|
||||||
|
} else {
|
||||||
|
this._WriteCharacter(buf[i], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._WriteCharacter = function (key, bControlKey) {
|
||||||
|
var rec = GM.CreateVariable(20);
|
||||||
|
rec.Deref(0, 2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType
|
||||||
|
rec.Deref(4, 4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown
|
||||||
|
rec.Deref(16, 4).toBuffer().writeUInt32LE(bControlKey); // rec.Event.KeyEvent.dwControlKeyState
|
||||||
|
rec.Deref(14, 1).toBuffer()[0] = key; // rec.Event.KeyEvent.uChar.AsciiChar
|
||||||
|
rec.Deref(8, 2).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.wRepeatCount
|
||||||
|
rec.Deref(10, 2).toBuffer().writeUInt16LE(this._user32.VkKeyScanA(key).Val); // rec.Event.KeyEvent.wVirtualKeyCode
|
||||||
|
rec.Deref(12, 2).toBuffer().writeUInt16LE(this._user32.MapVirtualKeyA(this._user32.VkKeyScanA(key).Val, MAPVK_VK_TO_VSC).Val);
|
||||||
|
|
||||||
|
var dwWritten = GM.CreateVariable(4);
|
||||||
|
if (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val == 0) { return (false); }
|
||||||
|
|
||||||
|
rec.Deref(4, 4).toBuffer().writeUInt16LE(0); // rec.Event.KeyEvent.bKeyDown
|
||||||
|
return (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current visible screen buffer
|
||||||
|
this._GetScreenBuffer = function (sx, sy, ex, ey) {
|
||||||
|
var info = GM.CreateVariable(22);
|
||||||
|
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
|
||||||
|
|
||||||
|
var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
|
||||||
|
var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
|
||||||
|
|
||||||
|
if (arguments[3] == null) {
|
||||||
|
// Use Default Parameters
|
||||||
|
sx = 0;
|
||||||
|
sy = 0;
|
||||||
|
ex = nWidth - 1;
|
||||||
|
ey = nHeight - 1;
|
||||||
|
} else {
|
||||||
|
if (this._scrx != 0) { sx += this._scrx; ex += this._scrx; }
|
||||||
|
if (this._scry != 0) { sy += this._scry; ey += this._scry; }
|
||||||
|
this._scrx = this._scry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nBuffer = GM.CreateVariable((ex - sx + 1) * (ey - sy + 1) * 4);
|
||||||
|
var size = GM.CreateVariable(4);
|
||||||
|
size.Deref(0, 2).toBuffer().writeUInt16LE(ex - sx + 1, 0);
|
||||||
|
size.Deref(2, 2).toBuffer().writeUInt16LE(ey - sy + 1, 0);
|
||||||
|
|
||||||
|
var startCoord = GM.CreateVariable(4);
|
||||||
|
startCoord.Deref(0, 2).toBuffer().writeUInt16LE(0, 0);
|
||||||
|
startCoord.Deref(2, 2).toBuffer().writeUInt16LE(0, 0);
|
||||||
|
|
||||||
|
var region = GM.CreateVariable(8);
|
||||||
|
region.buffer = region.toBuffer();
|
||||||
|
region.buffer.writeUInt16LE(sx, 0);
|
||||||
|
region.buffer.writeUInt16LE(sy, 2);
|
||||||
|
region.buffer.writeUInt16LE(ex, 4);
|
||||||
|
region.buffer.writeUInt16LE(ey, 6);
|
||||||
|
|
||||||
|
if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0) {
|
||||||
|
throw ('Unable to read Console Output');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lets convert the buffer into something simpler
|
||||||
|
//var retVal = { data: Buffer.alloc((dw - dx + 1) * (dh - dy + 1)), attributes: Buffer.alloc((dw - dx + 1) * (dh - dy + 1)), width: dw - dx + 1, height: dh - dy + 1, x: dx, y: dy };
|
||||||
|
|
||||||
|
var retVal = { data: [], attributes: [], width: ex - sx + 1, height: ey - sy + 1, x: sx, y: sy };
|
||||||
|
var x, y, line, ifo, tmp, lineWidth = ex - sx + 1;
|
||||||
|
|
||||||
|
for (y = 0; y <= (ey - sy) ; ++y) {
|
||||||
|
retVal.data.push(Buffer.alloc(lineWidth));
|
||||||
|
retVal.attributes.push(Buffer.alloc(lineWidth));
|
||||||
|
|
||||||
|
line = nBuffer.Deref(y * lineWidth * 4, lineWidth * 4).toBuffer();
|
||||||
|
for (x = 0; x < lineWidth; ++x) {
|
||||||
|
retVal.data.peek()[x] = line[x * 4];
|
||||||
|
retVal.attributes.peek()[x] = line[2 + (x * 4)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._SendDataBuffer = function (data) {
|
||||||
|
// { data, attributes, width, height, x, y }
|
||||||
|
|
||||||
|
var dy, line, attr;
|
||||||
|
for (dy = 0; dy < data.height; ++dy) {
|
||||||
|
line = data.data[dy];
|
||||||
|
attr = data.attributes[dy];
|
||||||
|
line.s = line.toString();
|
||||||
|
|
||||||
|
//line = data.data.slice(data.width * dy, (data.width * dy) + data.width);
|
||||||
|
//attr = data.attributes.slice(data.width * dy, (data.width * dy) + data.width);
|
||||||
|
this._stream.push(TranslateLine(data.x + 1, data.y + dy + 1, line, attr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._SendScroll = function _SendScroll(dx, dy) {
|
||||||
|
if (this._scrollTimer) { return; }
|
||||||
|
|
||||||
|
var info = GM.CreateVariable(22);
|
||||||
|
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
|
||||||
|
|
||||||
|
var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
|
||||||
|
var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
|
||||||
|
|
||||||
|
this._stream.push(GetEsc('H', [nHeight - 1, 0]));
|
||||||
|
for (var i = 0; i > nHeight; ++i) { this._stream.push(Buffer.from('\r\n')); }
|
||||||
|
|
||||||
|
var buffer = this._GetScreenBuffer(0, 0, nWidth - 1, nHeight - 1);
|
||||||
|
this._SendDataBuffer(buffer);
|
||||||
|
|
||||||
|
this._scrollTimer = setTimeout(function (self, nw, nh) {
|
||||||
|
var buffer = self._GetScreenBuffer(0, 0, nw - 1, nh - 1);
|
||||||
|
self._SendDataBuffer(buffer);
|
||||||
|
self._scrollTimer = null;
|
||||||
|
}, 250, this, nWidth, nHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.StartCommand = function StartCommand() {
|
||||||
|
if (this._kernel32.CreateProcessA(GM.CreateVariable(process.env['windir'] + '\\system32\\cmd.exe'), 0, 0, 0, 1, CREATE_NEW_PROCESS_GROUP, 0, 0, si, pi).Val == 0) {
|
||||||
|
console.log('Error Spawning CMD');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._kernel32.CloseHandle(pi.Deref(GM.PointerSize, GM.PointerSize).Deref()); // pi.hThread
|
||||||
|
this._hProcess = pi.Deref(0, GM.PointerSize).Deref(); // pi.hProcess
|
||||||
|
this._hProcessID = pi.Deref(GM.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE(); // pi.dwProcessId
|
||||||
|
//console.log('Ready => hProcess: ' + this._hProcess._ptr + ' PID: ' + this._hProcessID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function LOWORD(val) { return (val & 0xFFFF); }
|
||||||
|
function HIWORD(val) { return ((val >> 16) & 0xFFFF); }
|
||||||
|
function GetEsc(op, args) { return (Buffer.from('\x1B[' + args.join(';') + op)); }
|
||||||
|
function MeshConsole(msg) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": JSON.stringify(msg) }); }
|
||||||
|
function TranslateLine(x, y, data, attributes) {
|
||||||
|
var i, fcolor, bcolor, rcolor, fbright, bbright, lastAttr, fc, bc, rc, fb, bb, esc = [], output = [GetEsc('H', [y, x])];
|
||||||
|
if (typeof attributes == 'number') { attributes = [ attributes ]; } // If we get a single attribute, turn it into an array.
|
||||||
|
|
||||||
|
for (i = 0; i < data.length; i++) {
|
||||||
|
if (lastAttr != attributes[i]) { // To boost performance, if the attribute is the same as the last one, skip this entire part.
|
||||||
|
fc = (attributes[i] & 0x0007);
|
||||||
|
fc = ((fc & 0x0001) << 2) + (fc & 0x0002) + ((fc & 0x0004) >> 2); // Foreground color
|
||||||
|
bc = (attributes[i] & 0x0070) >> 4;
|
||||||
|
bc = ((bc & 0x0001) << 2) + (bc & 0x0002) + ((bc & 0x0004) >> 2); // Background color
|
||||||
|
rc = (attributes[i] & 0x4000); // Reverse color set
|
||||||
|
fb = (attributes[i] & 0x0008) >> 3; // Bright foreground set
|
||||||
|
bb = (attributes[i] & 0x0080); // Bright background set
|
||||||
|
|
||||||
|
if (rc != rcolor) { if (rc != 0) { esc.push(7); } else { esc.push(0); fcolor = 7; bcolor = 0; fbright = 0; bbright = 0; } rcolor = rc; } // Reverse Color
|
||||||
|
if (fc != fcolor) { esc.push(fc + 30); fcolor = fc; } // Set the foreground color if needed
|
||||||
|
if (bc != bcolor) { esc.push(bc + 40); bcolor = bc; } // Set the background color if needed
|
||||||
|
if (fb != fbright) { esc.push(2 - fb); fbright = fb; } // Set the bright foreground color if needed
|
||||||
|
if (bb != bbright) { if (bb == 0) { esc.push(bcolor + 40); } else { esc.push(bcolor + 100); bbright = bb; } } // Set bright Background color if needed
|
||||||
|
|
||||||
|
if (esc.length > 0) { output.push(GetEsc('m', esc)); esc = []; }
|
||||||
|
lastAttr = attributes[i];
|
||||||
|
}
|
||||||
|
output.push(Buffer.from(String.fromCharCode(data[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Buffer.concat(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new windows_terminal();
|
178
agents-new/modules_meshcore/x/clipboard.js
Normal file
178
agents-new/modules_meshcore/x/clipboard.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var promise = require('promise');
|
||||||
|
|
||||||
|
function nativeAddModule(name)
|
||||||
|
{
|
||||||
|
var value = getJSModule(name);
|
||||||
|
var ret = "duk_peval_string_noresult(ctx, \"addModule('" + name + "', Buffer.from('" + Buffer.from(value).toString('base64') + "', 'base64').toString());\");";
|
||||||
|
module.exports(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lin_readtext()
|
||||||
|
{
|
||||||
|
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('monitor-info')
|
||||||
|
}
|
||||||
|
catch(exc)
|
||||||
|
{
|
||||||
|
ret._rej(exc);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
var X11 = require('monitor-info')._X11;
|
||||||
|
if (!X11)
|
||||||
|
{
|
||||||
|
ret._rej('X11 required for Clipboard Manipulation');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var SelectionNotify = 31;
|
||||||
|
var AnyPropertyType = 0;
|
||||||
|
var GM = require('monitor-info')._gm;
|
||||||
|
|
||||||
|
ret._getInfoPromise = require('monitor-info').getInfo();
|
||||||
|
ret._getInfoPromise._masterPromise = ret;
|
||||||
|
ret._getInfoPromise.then(function (mon)
|
||||||
|
{
|
||||||
|
if (mon.length > 0)
|
||||||
|
{
|
||||||
|
var white = X11.XWhitePixel(mon[0].display, mon[0].screenId).Val;
|
||||||
|
|
||||||
|
this._masterPromise.CLIPID = X11.XInternAtom(mon[0].display, GM.CreateVariable('CLIPBOARD'), 0);
|
||||||
|
this._masterPromise.FMTID = X11.XInternAtom(mon[0].display, GM.CreateVariable('UTF8_STRING'), 0);
|
||||||
|
this._masterPromise.PROPID = X11.XInternAtom(mon[0].display, GM.CreateVariable('XSEL_DATA'), 0);
|
||||||
|
this._masterPromise.INCRID = X11.XInternAtom(mon[0].display, GM.CreateVariable('INCR'), 0);
|
||||||
|
this._masterPromise.ROOTWIN = X11.XRootWindow(mon[0].display, mon[0].screenId);
|
||||||
|
this._masterPromise.FAKEWIN = X11.XCreateSimpleWindow(mon[0].display, this._masterPromise.ROOTWIN, 0, 0, mon[0].right, 5, 0, white, white);
|
||||||
|
|
||||||
|
X11.XSync(mon[0].display, 0);
|
||||||
|
X11.XConvertSelection(mon[0].display, this._masterPromise.CLIPID, this._masterPromise.FMTID, this._masterPromise.PROPID, this._masterPromise.FAKEWIN, 0);
|
||||||
|
X11.XSync(mon[0].display, 0);
|
||||||
|
|
||||||
|
this._masterPromise.DescriptorEvent = require('DescriptorEvents').addDescriptor(X11.XConnectionNumber(mon[0].display).Val, { readset: true });
|
||||||
|
this._masterPromise.DescriptorEvent._masterPromise = this._masterPromise;
|
||||||
|
this._masterPromise.DescriptorEvent._display = mon[0].display;
|
||||||
|
this._masterPromise.DescriptorEvent.on('readset', function (fd)
|
||||||
|
{
|
||||||
|
var XE = GM.CreateVariable(1024);
|
||||||
|
while (X11.XPending(this._display).Val)
|
||||||
|
{
|
||||||
|
X11.XNextEventSync(this._display, XE);
|
||||||
|
if(XE.Deref(0, 4).toBuffer().readUInt32LE() == SelectionNotify)
|
||||||
|
{
|
||||||
|
var id = GM.CreatePointer();
|
||||||
|
var bits = GM.CreatePointer();
|
||||||
|
var sz = GM.CreatePointer();
|
||||||
|
var tail = GM.CreatePointer();
|
||||||
|
var result = GM.CreatePointer();
|
||||||
|
|
||||||
|
X11.XGetWindowProperty(this._display, this._masterPromise.FAKEWIN, this._masterPromise.PROPID, 0, 65535, 0, AnyPropertyType, id, bits, sz, tail, result);
|
||||||
|
this._masterPromise._res(result.Deref().String);
|
||||||
|
X11.XFree(result.Deref());
|
||||||
|
X11.XDestroyWindow(this._display, this._masterPromise.FAKEWIN);
|
||||||
|
|
||||||
|
this.removeDescriptor(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
function lin_copytext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_readtext()
|
||||||
|
{
|
||||||
|
var ret = '';
|
||||||
|
var CF_TEXT = 1;
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
var user32 = GM.CreateNativeProxy('user32.dll');
|
||||||
|
var kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||||
|
kernel32.CreateMethod('GlobalAlloc');
|
||||||
|
kernel32.CreateMethod('GlobalLock');
|
||||||
|
kernel32.CreateMethod('GlobalUnlock');
|
||||||
|
user32.CreateMethod('OpenClipboard');
|
||||||
|
user32.CreateMethod('CloseClipboard');
|
||||||
|
user32.CreateMethod('GetClipboardData');
|
||||||
|
|
||||||
|
user32.OpenClipboard(0);
|
||||||
|
var h = user32.GetClipboardData(CF_TEXT);
|
||||||
|
if(h.Val!=0)
|
||||||
|
{
|
||||||
|
var hbuffer = kernel32.GlobalLock(h);
|
||||||
|
ret = hbuffer.String;
|
||||||
|
kernel32.GlobalUnlock(h);
|
||||||
|
}
|
||||||
|
user32.CloseClipboard();
|
||||||
|
|
||||||
|
var p = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||||
|
p._res(ret);
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_copytext(txt)
|
||||||
|
{
|
||||||
|
var GMEM_MOVEABLE = 0x0002;
|
||||||
|
var CF_TEXT = 1;
|
||||||
|
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
var user32 = GM.CreateNativeProxy('user32.dll');
|
||||||
|
var kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||||
|
kernel32.CreateMethod('GlobalAlloc');
|
||||||
|
kernel32.CreateMethod('GlobalLock');
|
||||||
|
kernel32.CreateMethod('GlobalUnlock');
|
||||||
|
user32.CreateMethod('OpenClipboard');
|
||||||
|
user32.CreateMethod('EmptyClipboard');
|
||||||
|
user32.CreateMethod('CloseClipboard');
|
||||||
|
user32.CreateMethod('SetClipboardData');
|
||||||
|
|
||||||
|
var h = kernel32.GlobalAlloc(GMEM_MOVEABLE, txt.length + 2);
|
||||||
|
h.autoFree(false);
|
||||||
|
var hbuffer = kernel32.GlobalLock(h);
|
||||||
|
hbuffer.autoFree(false);
|
||||||
|
var tmp = Buffer.alloc(txt.length + 1);
|
||||||
|
Buffer.from(txt).copy(tmp);
|
||||||
|
tmp.copy(hbuffer.Deref(0, txt.length + 1).toBuffer());
|
||||||
|
kernel32.GlobalUnlock(h);
|
||||||
|
|
||||||
|
user32.OpenClipboard(0);
|
||||||
|
user32.EmptyClipboard();
|
||||||
|
user32.SetClipboardData(CF_TEXT, h);
|
||||||
|
user32.CloseClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(process.platform)
|
||||||
|
{
|
||||||
|
case 'win32':
|
||||||
|
module.exports = win_copytext;
|
||||||
|
module.exports.read = win_readtext;
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
module.exports = lin_copytext;
|
||||||
|
module.exports.read = lin_readtext;
|
||||||
|
break;
|
||||||
|
case 'darwin':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
module.exports.nativeAddModule = nativeAddModule;
|
313
agents-new/modules_meshcore/x/monitor-info.js
Normal file
313
agents-new/modules_meshcore/x/monitor-info.js
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var promise = require('promise');
|
||||||
|
var PPosition = 4;
|
||||||
|
var PSize = 8;
|
||||||
|
var _NET_WM_STATE_REMOVE = 0; // remove/unset property
|
||||||
|
var _NET_WM_STATE_ADD = 1; // add/set property
|
||||||
|
var _NET_WM_STATE_TOGGLE = 2; // toggle property
|
||||||
|
var SubstructureRedirectMask = (1 << 20);
|
||||||
|
var SubstructureNotifyMask = (1 << 19);
|
||||||
|
|
||||||
|
function getLibInfo(libname)
|
||||||
|
{
|
||||||
|
if (process.platform != 'linux') { throw ('Only supported on linux'); }
|
||||||
|
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write("ldconfig -p | grep '" + libname + ".so.'\nexit\n");
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var v = [];
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
for (var i in lines) {
|
||||||
|
if (lines[i]) {
|
||||||
|
var info = lines[i].split('=>');
|
||||||
|
var pth = info[1].trim();
|
||||||
|
var libinfo = info[0].trim().split(' ');
|
||||||
|
var lib = libinfo[0];
|
||||||
|
var plat = libinfo[1].substring(1, libinfo[1].length - 1).split(',');
|
||||||
|
|
||||||
|
if (lib.startsWith(libname + '.so.')) {
|
||||||
|
v.push({ lib: lib, path: pth, info: plat });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
function monitorinfo()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'monitor-info';
|
||||||
|
this._gm = require('_GenericMarshal');
|
||||||
|
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this._user32 = this._gm.CreateNativeProxy('user32.dll');
|
||||||
|
this._user32.CreateMethod('EnumDisplayMonitors');
|
||||||
|
this._kernel32 = this._gm.CreateNativeProxy('kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
this.getInfo = function getInfo()
|
||||||
|
{
|
||||||
|
var info = this;
|
||||||
|
return (new promise(function (resolver, rejector) {
|
||||||
|
this._monitorinfo = { resolver: resolver, rejector: rejector, self: info, callback: info._gm.GetGenericGlobalCallback(4) };
|
||||||
|
this._monitorinfo.callback.info = this._monitorinfo;
|
||||||
|
this._monitorinfo.dwData = info._gm.ObjectToPtr(this._monitorinfo);
|
||||||
|
|
||||||
|
this._monitorinfo.callback.results = [];
|
||||||
|
this._monitorinfo.callback.on('GlobalCallback', function OnMonitorInfo(hmon, hdc, r, user) {
|
||||||
|
if (this.ObjectToPtr_Verify(this.info, user)) {
|
||||||
|
var rb = r.Deref(0, 16).toBuffer();
|
||||||
|
this.results.push({ left: rb.readInt32LE(0), top: rb.readInt32LE(4), right: rb.readInt32LE(8), bottom: rb.readInt32LE(12) });
|
||||||
|
|
||||||
|
var r = this.info.self._gm.CreateInteger();
|
||||||
|
r.Val = 1;
|
||||||
|
return (r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (info._user32.EnumDisplayMonitors(0, 0, this._monitorinfo.callback, this._monitorinfo.dwData).Val == 0) {
|
||||||
|
rejector('LastError=' + info._kernel32.GetLastError().Val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolver(this._monitorinfo.callback.results);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
// First thing we need to do, is determine where the X11 libraries are
|
||||||
|
var askOS = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (require('user-sessions').isRoot()) { askOS = true; }
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
if (askOS)
|
||||||
|
{
|
||||||
|
// Sufficient access rights to use ldconfig
|
||||||
|
var x11info = getLibInfo('libX11');
|
||||||
|
var xtstinfo = getLibInfo('libXtst');
|
||||||
|
var xextinfo = getLibInfo('libXext');
|
||||||
|
var ix;
|
||||||
|
|
||||||
|
for(ix in x11info)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._gm.CreateNativeProxy(x11info[ix].path);
|
||||||
|
Object.defineProperty(this, 'Location_X11LIB', { value: x11info[ix].path });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch(ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ix in xtstinfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._gm.CreateNativeProxy(xtstinfo[ix].path);
|
||||||
|
Object.defineProperty(this, 'Location_X11TST', { value: xtstinfo[ix].path });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ix in xextinfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._gm.CreateNativeProxy(xextinfo[ix].path);
|
||||||
|
Object.defineProperty(this, 'Location_X11EXT', { value: xextinfo[ix].path });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not enough access rights to use ldconfig, so manually search
|
||||||
|
var fs = require('fs');
|
||||||
|
var files = fs.readdirSync('/usr/lib');
|
||||||
|
var files2;
|
||||||
|
|
||||||
|
for (var i in files) {
|
||||||
|
try {
|
||||||
|
if (files[i].split('libX11.so.').length > 1 && files[i].split('.').length == 3) {
|
||||||
|
Object.defineProperty(this, 'Location_X11LIB', { value: '/usr/lib/' + files[i] });
|
||||||
|
}
|
||||||
|
if (files[i].split('libXtst.so.').length > 1 && files[i].split('.').length == 3) {
|
||||||
|
Object.defineProperty(this, 'Location_X11TST', { value: '/usr/lib/' + files[i] });
|
||||||
|
}
|
||||||
|
if (files[i].split('libXext.so.').length > 1 && files[i].split('.').length == 3) {
|
||||||
|
Object.defineProperty(this, 'Location_X11EXT', { value: '/usr/lib/' + files[i] });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (files[i].split('-linux-').length > 1) {
|
||||||
|
files2 = fs.readdirSync('/usr/lib/' + files[i]);
|
||||||
|
for (j in files2) {
|
||||||
|
if (files2[j].split('libX11.so.').length > 1 && files2[j].split('.').length == 3) {
|
||||||
|
Object.defineProperty(this, 'Location_X11LIB', { value: '/usr/lib/' + files[i] + '/' + files2[j] });
|
||||||
|
}
|
||||||
|
if (files2[j].split('libXtst.so.').length > 1 && files2[j].split('.').length == 3) {
|
||||||
|
Object.defineProperty(this, 'Location_X11TST', { value: '/usr/lib/' + files[i] + '/' + files2[j] });
|
||||||
|
}
|
||||||
|
if (files2[j].split('libXext.so.').length > 1 && files2[j].split('.').length == 3) {
|
||||||
|
Object.defineProperty(this, 'Location_X11EXT', { value: '/usr/lib/' + files[i] + '/' + files2[j] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ex) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.defineProperty(this, 'kvm_x11_support', { value: (this.Location_X11LIB && this.Location_X11TST && this.Location_X11EXT)?true:false });
|
||||||
|
|
||||||
|
if (this.Location_X11LIB)
|
||||||
|
{
|
||||||
|
this._X11 = this._gm.CreateNativeProxy(this.Location_X11LIB);
|
||||||
|
this._X11.CreateMethod('XChangeProperty');
|
||||||
|
this._X11.CreateMethod('XCloseDisplay');
|
||||||
|
this._X11.CreateMethod('XConnectionNumber');
|
||||||
|
this._X11.CreateMethod('XConvertSelection');
|
||||||
|
this._X11.CreateMethod('XCreateGC');
|
||||||
|
this._X11.CreateMethod('XCreateWindow');
|
||||||
|
this._X11.CreateMethod('XCreateSimpleWindow');
|
||||||
|
this._X11.CreateMethod('XDefaultColormap');
|
||||||
|
this._X11.CreateMethod('XDefaultScreen');
|
||||||
|
this._X11.CreateMethod('XDestroyWindow');
|
||||||
|
this._X11.CreateMethod('XDrawLine');
|
||||||
|
this._X11.CreateMethod('XDisplayHeight');
|
||||||
|
this._X11.CreateMethod('XDisplayWidth');
|
||||||
|
this._X11.CreateMethod('XFetchName');
|
||||||
|
this._X11.CreateMethod('XFlush');
|
||||||
|
this._X11.CreateMethod('XFree');
|
||||||
|
this._X11.CreateMethod('XCreateGC');
|
||||||
|
this._X11.CreateMethod('XGetWindowProperty');
|
||||||
|
this._X11.CreateMethod('XInternAtom');
|
||||||
|
this._X11.CreateMethod('XMapWindow');
|
||||||
|
this._X11.CreateMethod({ method: 'XNextEvent', threadDispatch: true });
|
||||||
|
this._X11.CreateMethod({ method: 'XNextEvent', newName: 'XNextEventSync' });
|
||||||
|
this._X11.CreateMethod('XOpenDisplay');
|
||||||
|
this._X11.CreateMethod('XPending');
|
||||||
|
this._X11.CreateMethod('XRootWindow');
|
||||||
|
this._X11.CreateMethod('XSelectInput');
|
||||||
|
this._X11.CreateMethod('XScreenCount');
|
||||||
|
this._X11.CreateMethod('XScreenOfDisplay');
|
||||||
|
this._X11.CreateMethod('XSelectInput');
|
||||||
|
this._X11.CreateMethod('XSendEvent');
|
||||||
|
this._X11.CreateMethod('XSetForeground');
|
||||||
|
this._X11.CreateMethod('XSetFunction');
|
||||||
|
this._X11.CreateMethod('XSetLineAttributes');
|
||||||
|
this._X11.CreateMethod('XSetNormalHints');
|
||||||
|
this._X11.CreateMethod('XSetSubwindowMode');
|
||||||
|
this._X11.CreateMethod('XSync');
|
||||||
|
this._X11.CreateMethod('XBlackPixel');
|
||||||
|
this._X11.CreateMethod('XWhitePixel');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isUnity = function isUnity()
|
||||||
|
{
|
||||||
|
return (process.env['XDG_CURRENT_DESKTOP'] == 'Unity');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unDecorateWindow = function unDecorateWindow(display, window)
|
||||||
|
{
|
||||||
|
var MwmHints = this._gm.CreateVariable(40);
|
||||||
|
var mwmHintsProperty = this._X11.XInternAtom(display, this._gm.CreateVariable('_MOTIF_WM_HINTS'), 0);
|
||||||
|
MwmHints.Deref(0, 4).toBuffer().writeUInt32LE(1 << 1);
|
||||||
|
this._X11.XChangeProperty(display, window, mwmHintsProperty, mwmHintsProperty, 32, 0, MwmHints, 5);
|
||||||
|
}
|
||||||
|
this.setWindowSizeHints = function setWindowSizeHints(display, window, x, y, width, height)
|
||||||
|
{
|
||||||
|
var sizeHints = this._gm.CreateVariable(80);
|
||||||
|
sizeHints.Deref(0, 4).toBuffer().writeUInt32LE(PPosition | PSize);
|
||||||
|
sizeHints.Deref(8, 4).toBuffer().writeUInt32LE(x);
|
||||||
|
sizeHints.Deref(12, 4).toBuffer().writeUInt32LE(y);
|
||||||
|
sizeHints.Deref(16, 4).toBuffer().writeUInt32LE(width);
|
||||||
|
sizeHints.Deref(20, 4).toBuffer().writeUInt32LE(height);
|
||||||
|
this._X11.XSetNormalHints(display, window, sizeHints);
|
||||||
|
}
|
||||||
|
this.setAlwaysOnTop = function setAlwaysOnTop(display, rootWindow, window)
|
||||||
|
{
|
||||||
|
var wmNetWmState = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE'), 1);
|
||||||
|
var wmStateAbove = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE_ABOVE'), 1);
|
||||||
|
|
||||||
|
var xclient = this._gm.CreateVariable(96);
|
||||||
|
xclient.Deref(0, 4).toBuffer().writeUInt32LE(33); // ClientMessage type
|
||||||
|
xclient.Deref(48, 4).toBuffer().writeUInt32LE(32); // Format 32
|
||||||
|
wmNetWmState.pointerBuffer().copy(xclient.Deref(40, 8).toBuffer()); // message_type
|
||||||
|
xclient.Deref(56, 8).toBuffer().writeUInt32LE(_NET_WM_STATE_ADD); // data.l[0]
|
||||||
|
wmStateAbove.pointerBuffer().copy(xclient.Deref(64, 8).toBuffer()); // data.l[1]
|
||||||
|
|
||||||
|
window.pointerBuffer().copy(xclient.Deref(32, 8).toBuffer()); // window
|
||||||
|
this._X11.XSendEvent(display, rootWindow, 0, SubstructureRedirectMask | SubstructureNotifyMask, xclient);
|
||||||
|
}
|
||||||
|
this.hideWindowIcon = function hideWindowIcon(display, rootWindow, window)
|
||||||
|
{
|
||||||
|
var wmNetWmState = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE'), 1);
|
||||||
|
var wmStateSkip = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE_SKIP_TASKBAR'), 1);
|
||||||
|
|
||||||
|
var xclient = this._gm.CreateVariable(96);
|
||||||
|
xclient.Deref(0, 4).toBuffer().writeUInt32LE(33); // ClientMessage type
|
||||||
|
xclient.Deref(48, 4).toBuffer().writeUInt32LE(32); // Format 32
|
||||||
|
wmNetWmState.pointerBuffer().copy(xclient.Deref(40, 8).toBuffer()); // message_type
|
||||||
|
xclient.Deref(56, 8).toBuffer().writeUInt32LE(_NET_WM_STATE_ADD); // data.l[0]
|
||||||
|
wmStateSkip.pointerBuffer().copy(xclient.Deref(64, 8).toBuffer()); // data.l[1]
|
||||||
|
|
||||||
|
window.pointerBuffer().copy(xclient.Deref(32, 8).toBuffer()); // window
|
||||||
|
this._X11.XSendEvent(display, rootWindow, 0, SubstructureRedirectMask | SubstructureNotifyMask, xclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getInfo = function getInfo()
|
||||||
|
{
|
||||||
|
var info = this;
|
||||||
|
return (new promise(function (resolver, rejector)
|
||||||
|
{
|
||||||
|
var display = info._X11.XOpenDisplay(info._gm.CreateVariable(':0'));
|
||||||
|
var screenCount = info._X11.XScreenCount(display).Val;
|
||||||
|
var ret = [];
|
||||||
|
for(var i=0;i<screenCount;++i)
|
||||||
|
{
|
||||||
|
var screen = info._X11.XScreenOfDisplay(display, i);
|
||||||
|
ret.push({ left: 0, top: 0, right: info._X11.XDisplayWidth(display, i).Val, bottom: info._X11.XDisplayHeight(display, i).Val, screen: screen, screenId: i, display: display });
|
||||||
|
}
|
||||||
|
resolver(ret);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw (process.platform + ' not supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new monitorinfo();
|
||||||
|
|
||||||
|
|
||||||
|
|
163
agents-new/modules_meshcore/x/process-manager.js
Normal file
163
agents-new/modules_meshcore/x/process-manager.js
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
|
||||||
|
// Used on Windows and Linux to get information about running processes
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
case 'win32':
|
||||||
|
this._kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._kernel32.CreateMethod('CreateToolhelp32Snapshot');
|
||||||
|
this._kernel32.CreateMethod('Process32First');
|
||||||
|
this._kernel32.CreateMethod('Process32Next');
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
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:
|
||||||
|
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||||
|
break;
|
||||||
|
case 'win32': // Windows processes
|
||||||
|
var retVal = {};
|
||||||
|
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0);
|
||||||
|
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)] = { 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]); }
|
||||||
|
break;
|
||||||
|
case 'linux': // Linux processes
|
||||||
|
if (!this._psp) { this._psp = {}; }
|
||||||
|
var p = this._childProcess.execFile("/bin/ps", ["ps", "-uxa"], { type: this._childProcess.SpawnTypes.TERM });
|
||||||
|
this._psp[p.pid] = p;
|
||||||
|
p.Parent = this;
|
||||||
|
p.ps = '';
|
||||||
|
p.callback = callback;
|
||||||
|
p.args = [];
|
||||||
|
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||||
|
p.on('exit', function onGetProcesses()
|
||||||
|
{
|
||||||
|
delete this.Parent._psp[this.pid];
|
||||||
|
var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
||||||
|
for (var i in lines)
|
||||||
|
{
|
||||||
|
var tokens = lines[i].split(' ');
|
||||||
|
var tokenList = [];
|
||||||
|
for(var x in tokens)
|
||||||
|
{
|
||||||
|
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
||||||
|
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]);}
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { pid: key.PID, user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.callback)
|
||||||
|
{
|
||||||
|
this.args.unshift(retVal);
|
||||||
|
this.callback.apply(this.parent, this.args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
||||||
|
break;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
throw ('getProcessInfo() not supported for ' + process.platform);
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
var status = require('fs').readFileSync('/proc/' + pid + '/status');
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
return (info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new processManager();
|
497
agents-new/modules_meshcore/x/service-manager.js
Normal file
497
agents-new/modules_meshcore/x/service-manager.js
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
/*
|
||||||
|
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 parseServiceStatus(token)
|
||||||
|
{
|
||||||
|
var j = {};
|
||||||
|
var serviceType = token.Deref(0, 4).IntVal;
|
||||||
|
j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
|
||||||
|
j.isKernelDriver = ((serviceType & 0x00000001) == 0x00000001);
|
||||||
|
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
|
||||||
|
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
|
||||||
|
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
|
||||||
|
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
|
||||||
|
{
|
||||||
|
case 0x00000005:
|
||||||
|
j.state = 'CONTINUE_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000006:
|
||||||
|
j.state = 'PAUSE_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000007:
|
||||||
|
j.state = 'PAUSED';
|
||||||
|
break;
|
||||||
|
case 0x00000004:
|
||||||
|
j.state = 'RUNNING';
|
||||||
|
break;
|
||||||
|
case 0x00000002:
|
||||||
|
j.state = 'START_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000003:
|
||||||
|
j.state = 'STOP_PENDING';
|
||||||
|
break;
|
||||||
|
case 0x00000001:
|
||||||
|
j.state = 'STOPPED';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
|
||||||
|
j.controlsAccepted = [];
|
||||||
|
if ((controlsAccepted & 0x00000010) == 0x00000010)
|
||||||
|
{
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
|
||||||
|
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDDISABLE');
|
||||||
|
}
|
||||||
|
if ((controlsAccepted & 0x00000008) == 0x00000008) { j.controlsAccepted.push('SERVICE_CONTROL_PARAMCHANGE'); }
|
||||||
|
if ((controlsAccepted & 0x00000002) == 0x00000002) { j.controlsAccepted.push('SERVICE_CONTROL_PAUSE'); j.controlsAccepted.push('SERVICE_CONTROL_CONTINUE'); }
|
||||||
|
if ((controlsAccepted & 0x00000100) == 0x00000100) { j.controlsAccepted.push('SERVICE_CONTROL_PRESHUTDOWN'); }
|
||||||
|
if ((controlsAccepted & 0x00000004) == 0x00000004) { j.controlsAccepted.push('SERVICE_CONTROL_SHUTDOWN'); }
|
||||||
|
if ((controlsAccepted & 0x00000001) == 0x00000001) { j.controlsAccepted.push('SERVICE_CONTROL_STOP'); }
|
||||||
|
if ((controlsAccepted & 0x00000020) == 0x00000020) { j.controlsAccepted.push('SERVICE_CONTROL_HARDWAREPROFILECHANGE'); }
|
||||||
|
if ((controlsAccepted & 0x00000040) == 0x00000040) { j.controlsAccepted.push('SERVICE_CONTROL_POWEREVENT'); }
|
||||||
|
if ((controlsAccepted & 0x00000080) == 0x00000080) { j.controlsAccepted.push('SERVICE_CONTROL_SESSIONCHANGE'); }
|
||||||
|
j.pid = token.Deref((7 * 4), 4).toBuffer().readUInt32LE();
|
||||||
|
return (j);
|
||||||
|
}
|
||||||
|
|
||||||
|
function serviceManager()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'service-manager';
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this.GM = require('_GenericMarshal');
|
||||||
|
this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this.proxy.CreateMethod('OpenSCManagerA');
|
||||||
|
this.proxy.CreateMethod('EnumServicesStatusExA');
|
||||||
|
this.proxy.CreateMethod('OpenServiceA');
|
||||||
|
this.proxy.CreateMethod('QueryServiceStatusEx');
|
||||||
|
this.proxy.CreateMethod('ControlService');
|
||||||
|
this.proxy.CreateMethod('StartServiceA');
|
||||||
|
this.proxy.CreateMethod('CloseServiceHandle');
|
||||||
|
this.proxy.CreateMethod('CreateServiceA');
|
||||||
|
this.proxy.CreateMethod('ChangeServiceConfig2A');
|
||||||
|
this.proxy.CreateMethod('DeleteService');
|
||||||
|
this.proxy.CreateMethod('AllocateAndInitializeSid');
|
||||||
|
this.proxy.CreateMethod('CheckTokenMembership');
|
||||||
|
this.proxy.CreateMethod('FreeSid');
|
||||||
|
|
||||||
|
this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this.proxy2.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
this.isAdmin = function isAdmin() {
|
||||||
|
var NTAuthority = this.GM.CreateVariable(6);
|
||||||
|
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||||
|
var AdministratorsGroup = this.GM.CreatePointer();
|
||||||
|
var admin = false;
|
||||||
|
|
||||||
|
if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||||
|
{
|
||||||
|
var member = this.GM.CreateInteger();
|
||||||
|
if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||||
|
{
|
||||||
|
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||||
|
}
|
||||||
|
this.proxy.FreeSid(AdministratorsGroup.Deref());
|
||||||
|
}
|
||||||
|
return admin;
|
||||||
|
};
|
||||||
|
this.getProgramFolder = function getProgramFolder()
|
||||||
|
{
|
||||||
|
if (require('os').arch() == 'x64')
|
||||||
|
{
|
||||||
|
// 64 bit Windows
|
||||||
|
if (this.GM.PointerSize == 4)
|
||||||
|
{
|
||||||
|
return process.env['ProgramFiles(x86)']; // 32 Bit App
|
||||||
|
}
|
||||||
|
return process.env['ProgramFiles']; // 64 bit App
|
||||||
|
}
|
||||||
|
|
||||||
|
// 32 bit Windows
|
||||||
|
return process.env['ProgramFiles'];
|
||||||
|
};
|
||||||
|
this.getServiceFolder = function getServiceFolder() { return this.getProgramFolder() + '\\mesh'; };
|
||||||
|
|
||||||
|
this.enumerateService = function () {
|
||||||
|
var machineName = this.GM.CreatePointer();
|
||||||
|
var dbName = this.GM.CreatePointer();
|
||||||
|
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004);
|
||||||
|
|
||||||
|
var bytesNeeded = this.GM.CreatePointer();
|
||||||
|
var servicesReturned = this.GM.CreatePointer();
|
||||||
|
var resumeHandle = this.GM.CreatePointer();
|
||||||
|
//var services = this.proxy.CreateVariable(262144);
|
||||||
|
var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||||
|
if (bytesNeeded.IntVal <= 0) {
|
||||||
|
throw ('error enumerating services');
|
||||||
|
}
|
||||||
|
var sz = bytesNeeded.IntVal;
|
||||||
|
var services = this.GM.CreateVariable(sz);
|
||||||
|
this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||||
|
console.log("servicesReturned", servicesReturned.IntVal);
|
||||||
|
|
||||||
|
var ptrSize = dbName._size;
|
||||||
|
var blockSize = 36 + (2 * ptrSize);
|
||||||
|
blockSize += ((ptrSize - (blockSize % ptrSize)) % ptrSize);
|
||||||
|
var retVal = [];
|
||||||
|
for (var i = 0; i < servicesReturned.IntVal; ++i) {
|
||||||
|
var token = services.Deref(i * blockSize, blockSize);
|
||||||
|
var j = {};
|
||||||
|
j.name = token.Deref(0, ptrSize).Deref().String;
|
||||||
|
j.displayName = token.Deref(ptrSize, ptrSize).Deref().String;
|
||||||
|
j.status = parseServiceStatus(token.Deref(2 * ptrSize, 36));
|
||||||
|
retVal.push(j);
|
||||||
|
}
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
this.getService = function (name) {
|
||||||
|
var serviceName = this.GM.CreateVariable(name);
|
||||||
|
var ptr = this.GM.CreatePointer();
|
||||||
|
var bytesNeeded = this.GM.CreateVariable(ptr._size);
|
||||||
|
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
|
||||||
|
if (handle.Val == 0) { throw ('could not open ServiceManager'); }
|
||||||
|
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
|
||||||
|
if (h.Val != 0) {
|
||||||
|
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
|
||||||
|
var status = this.GM.CreateVariable(bytesNeeded.toBuffer().readUInt32LE());
|
||||||
|
success = this.proxy.QueryServiceStatusEx(h, 0, status, status._size, bytesNeeded);
|
||||||
|
if (success != 0) {
|
||||||
|
retVal = {};
|
||||||
|
retVal.status = parseServiceStatus(status);
|
||||||
|
retVal._scm = handle;
|
||||||
|
retVal._service = h;
|
||||||
|
retVal._GM = this.GM;
|
||||||
|
retVal._proxy = this.proxy;
|
||||||
|
require('events').inherits(retVal);
|
||||||
|
retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); });
|
||||||
|
retVal.name = name;
|
||||||
|
retVal.stop = function () {
|
||||||
|
if (this.status.state == 'RUNNING') {
|
||||||
|
var newstate = this._GM.CreateVariable(36);
|
||||||
|
var success = this._proxy.ControlService(this._service, 0x00000001, newstate);
|
||||||
|
if (success == 0) {
|
||||||
|
throw (this.name + '.stop() failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retVal.start = function () {
|
||||||
|
if (this.status.state == 'STOPPED') {
|
||||||
|
var success = this._proxy.StartServiceA(this._service, 0, 0);
|
||||||
|
if (success == 0) {
|
||||||
|
throw (this.name + '.start() failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
throw ('could not find service: ' + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.isAdmin = function isAdmin()
|
||||||
|
{
|
||||||
|
return (require('user-sessions').isRoot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.installService = function installService(options)
|
||||||
|
{
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
|
||||||
|
|
||||||
|
// Before we start, we need to copy the binary to the right place
|
||||||
|
var folder = this.getServiceFolder();
|
||||||
|
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
|
||||||
|
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
|
||||||
|
options.servicePath = folder + '\\' + options.name + '.exe';
|
||||||
|
|
||||||
|
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
|
||||||
|
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
|
||||||
|
if (handle.Val == 0) { throw ('error opening SCManager'); }
|
||||||
|
var serviceName = this.GM.CreateVariable(options.name);
|
||||||
|
var displayName = this.GM.CreateVariable(options.name);
|
||||||
|
var allAccess = 0x000F01FF;
|
||||||
|
var serviceType;
|
||||||
|
|
||||||
|
|
||||||
|
switch (options.startType) {
|
||||||
|
case 'BOOT_START':
|
||||||
|
serviceType = 0x00;
|
||||||
|
break;
|
||||||
|
case 'SYSTEM_START':
|
||||||
|
serviceType = 0x01;
|
||||||
|
break;
|
||||||
|
case 'AUTO_START':
|
||||||
|
serviceType = 0x02;
|
||||||
|
break;
|
||||||
|
case 'DEMAND_START':
|
||||||
|
serviceType = 0x03;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
serviceType = 0x04; // Disabled
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var h = this.proxy.CreateServiceA(handle, serviceName, displayName, allAccess, 0x10 | 0x100, serviceType, 0, servicePath, 0, 0, 0, 0, 0);
|
||||||
|
if (h.Val == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service: ' + this.proxy2.GetLastError().Val); }
|
||||||
|
if (options.description) {
|
||||||
|
console.log(options.description);
|
||||||
|
|
||||||
|
var dscPtr = this.GM.CreatePointer();
|
||||||
|
dscPtr.Val = this.GM.CreateVariable(options.description);
|
||||||
|
|
||||||
|
if (this.proxy.ChangeServiceConfig2A(h, 1, dscPtr) == 0) {
|
||||||
|
this.proxy.CloseServiceHandle(h);
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
throw ('Unable to set description');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.proxy.CloseServiceHandle(h);
|
||||||
|
this.proxy.CloseServiceHandle(handle);
|
||||||
|
return (this.getService(options.name));
|
||||||
|
}
|
||||||
|
if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||||
|
|
||||||
|
switch (this.getServiceType())
|
||||||
|
{
|
||||||
|
case 'init':
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
|
||||||
|
console.log('copying ' + options.servicePath);
|
||||||
|
var m = require('fs').statSync('/etc/init.d/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/etc/init.d/' + options.name, m);
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update._moduleName = options.name;
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('update-rc.d ' + options.name + ' defaults\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
//update-rc.d meshagent defaults # creates symlinks for rc.d
|
||||||
|
//service meshagent start
|
||||||
|
|
||||||
|
this._update.waitExit();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'systemd':
|
||||||
|
var serviceDescription = options.description ? options.description : 'MeshCentral Agent';
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh')) { require('fs').mkdirSync('/usr/local/mesh'); }
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh/' + options.name);
|
||||||
|
var m = require('fs').statSync('/usr/local/mesh/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/usr/local/mesh/' + options.name, m);
|
||||||
|
require('fs').writeFileSync('/lib/systemd/system/' + options.name + '.service', '[Unit]\nDescription=' + serviceDescription + '\n[Service]\nExecStart=/usr/local/mesh/' + options.name + '\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=' + options.name + '.service\n', { flags: 'w' });
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update._moduleName = options.name;
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('systemctl enable ' + options.name + '.service\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
this._update.waitExit();
|
||||||
|
break;
|
||||||
|
default: // unknown platform service type
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||||
|
|
||||||
|
// Mac OS
|
||||||
|
var stdoutpath = (options.stdout ? ('<key>StandardOutPath</key>\n<string>' + options.stdout + '</string>') : '');
|
||||||
|
var autoStart = (options.startType == 'AUTO_START' ? '<true/>' : '<false/>');
|
||||||
|
var params = ' <key>ProgramArguments</key>\n';
|
||||||
|
params += ' <array>\n';
|
||||||
|
params += (' <string>/usr/local/mesh_services/' + options.name + '/' + options.name + '</string>\n');
|
||||||
|
if(options.parameters)
|
||||||
|
{
|
||||||
|
for(var itm in options.parameters)
|
||||||
|
{
|
||||||
|
params += (' <string>' + options.parameters[itm] + '</string>\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params += ' </array>\n';
|
||||||
|
|
||||||
|
var plist = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||||
|
plist += '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
|
||||||
|
plist += '<plist version="1.0">\n';
|
||||||
|
plist += ' <dict>\n';
|
||||||
|
plist += ' <key>Label</key>\n';
|
||||||
|
plist += (' <string>' + options.name + '</string>\n');
|
||||||
|
plist += (params + '\n');
|
||||||
|
plist += ' <key>WorkingDirectory</key>\n';
|
||||||
|
plist += (' <string>/usr/local/mesh_services/' + options.name + '</string>\n');
|
||||||
|
plist += (stdoutpath + '\n');
|
||||||
|
plist += ' <key>RunAtLoad</key>\n';
|
||||||
|
plist += (autoStart + '\n');
|
||||||
|
plist += ' </dict>\n';
|
||||||
|
plist += '</plist>';
|
||||||
|
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_services')) { require('fs').mkdirSync('/usr/local/mesh_services'); }
|
||||||
|
if (!require('fs').existsSync('/Library/LaunchDaemons/' + options.name + '.plist'))
|
||||||
|
{
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_services/' + options.name)) { require('fs').mkdirSync('/usr/local/mesh_services/' + options.name); }
|
||||||
|
if (options.binary)
|
||||||
|
{
|
||||||
|
require('fs').writeFileSync('/usr/local/mesh_services/' + options.name + '/' + options.name, options.binary);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh_services/' + options.name + '/' + options.name);
|
||||||
|
}
|
||||||
|
require('fs').writeFileSync('/Library/LaunchDaemons/' + options.name + '.plist', plist);
|
||||||
|
var m = require('fs').statSync('/usr/local/mesh_services/' + options.name + '/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/usr/local/mesh_services/' + options.name + '/' + options.name, m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Service: ' + options.name + ' already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.uninstallService = function uninstallService(name)
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||||
|
|
||||||
|
if (typeof (name) == 'object') { name = name.name; }
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
var service = this.getService(name);
|
||||||
|
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
||||||
|
{
|
||||||
|
if (this.proxy.DeleteService(service._service) == 0)
|
||||||
|
{
|
||||||
|
throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
switch (this.getServiceType())
|
||||||
|
{
|
||||||
|
case 'init':
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('service ' + name + ' stop\n');
|
||||||
|
this._update.stdin.write('update-rc.d -f ' + name + ' remove\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
this._update.waitExit();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/etc/init.d/' + name);
|
||||||
|
console.log(name + ' uninstalled');
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(name + ' could not be uninstalled', e)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'systemd':
|
||||||
|
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
|
this._update.stdout.on('data', function (chunk) { });
|
||||||
|
this._update.stdin.write('systemctl stop ' + name + '.service\n');
|
||||||
|
this._update.stdin.write('systemctl disable ' + name + '.service\n');
|
||||||
|
this._update.stdin.write('exit\n');
|
||||||
|
this._update.waitExit();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/usr/local/mesh/' + name);
|
||||||
|
require('fs').unlinkSync('/lib/systemd/system/' + name + '.service');
|
||||||
|
console.log(name + ' uninstalled');
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(name + ' could not be uninstalled', e)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // unknown platform service type
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
if (require('fs').existsSync('/Library/LaunchDaemons/' + name + '.plist'))
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.on('data', function (chunk) { });
|
||||||
|
child.stdin.write('launchctl stop ' + name + '\n');
|
||||||
|
child.stdin.write('launchctl unload /Library/LaunchDaemons/' + name + '.plist\n');
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/usr/local/mesh_services/' + name + '/' + name);
|
||||||
|
require('fs').unlinkSync('/Library/LaunchDaemons/' + name + '.plist');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
throw ('Error uninstalling service: ' + name + ' => ' + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').rmdirSync('/usr/local/mesh_services/' + name);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Service: ' + name + ' does not exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(process.platform == 'linux')
|
||||||
|
{
|
||||||
|
this.getServiceType = function getServiceType()
|
||||||
|
{
|
||||||
|
return (require('process-manager').getProcessInfo(1).Name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = serviceManager;
|
750
agents-new/modules_meshcore/x/user-sessions.js
Normal file
750
agents-new/modules_meshcore/x/user-sessions.js
Normal file
@ -0,0 +1,750 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var 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);
|
||||||
|
var WTS_REMOTE_DISCONNECT = (0x4);
|
||||||
|
var WTS_SESSION_LOGON = (0x5);
|
||||||
|
var WTS_SESSION_LOGOFF = (0x6);
|
||||||
|
var WTS_SESSION_LOCK = (0x7);
|
||||||
|
var WTS_SESSION_UNLOCK = (0x8);
|
||||||
|
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';
|
||||||
|
require('events').EventEmitter.call(this, true)
|
||||||
|
.createEvent('changed')
|
||||||
|
.createEvent('locked')
|
||||||
|
.createEvent('unlocked');
|
||||||
|
|
||||||
|
this.enumerateUsers = function enumerateUsers()
|
||||||
|
{
|
||||||
|
var promise = require('promise');
|
||||||
|
var p = new promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__resolver = res;
|
||||||
|
this.__rejector = rej;
|
||||||
|
});
|
||||||
|
p.__handler = function __handler(users)
|
||||||
|
{
|
||||||
|
p.__resolver(users);
|
||||||
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.Current(p.__handler);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
p.__rejector(e);
|
||||||
|
}
|
||||||
|
p.parent = this;
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this._serviceHooked = false;
|
||||||
|
this._marshal = require('_GenericMarshal');
|
||||||
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||||
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||||
|
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||||
|
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||||
|
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||||
|
this._wts.CreateMethod('WTSFreeMemory');
|
||||||
|
}
|
||||||
|
catch(exc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
this._advapi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this._advapi.CreateMethod('AllocateAndInitializeSid');
|
||||||
|
this._advapi.CreateMethod('CheckTokenMembership');
|
||||||
|
this._advapi.CreateMethod('FreeSid');
|
||||||
|
|
||||||
|
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
||||||
|
this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1});
|
||||||
|
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 =
|
||||||
|
{
|
||||||
|
'WTSInitialProgram': 0,
|
||||||
|
'WTSApplicationName': 1,
|
||||||
|
'WTSWorkingDirectory': 2,
|
||||||
|
'WTSOEMId': 3,
|
||||||
|
'WTSSessionId': 4,
|
||||||
|
'WTSUserName': 5,
|
||||||
|
'WTSWinStationName': 6,
|
||||||
|
'WTSDomainName': 7,
|
||||||
|
'WTSConnectState': 8,
|
||||||
|
'WTSClientBuildNumber': 9,
|
||||||
|
'WTSClientName': 10,
|
||||||
|
'WTSClientDirectory': 11,
|
||||||
|
'WTSClientProductId': 12,
|
||||||
|
'WTSClientHardwareId': 13,
|
||||||
|
'WTSClientAddress': 14,
|
||||||
|
'WTSClientDisplay': 15,
|
||||||
|
'WTSClientProtocolType': 16,
|
||||||
|
'WTSIdleTime': 17,
|
||||||
|
'WTSLogonTime': 18,
|
||||||
|
'WTSIncomingBytes': 19,
|
||||||
|
'WTSOutgoingBytes': 20,
|
||||||
|
'WTSIncomingFrames': 21,
|
||||||
|
'WTSOutgoingFrames': 22,
|
||||||
|
'WTSClientInfo': 23,
|
||||||
|
'WTSSessionInfo': 24,
|
||||||
|
'WTSSessionInfoEx': 25,
|
||||||
|
'WTSConfigInfo': 26,
|
||||||
|
'WTSValidationInfo': 27,
|
||||||
|
'WTSSessionAddressV4': 28,
|
||||||
|
'WTSIsRemoteSession': 29
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isRoot = function isRoot()
|
||||||
|
{
|
||||||
|
var NTAuthority = this._marshal.CreateVariable(6);
|
||||||
|
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||||
|
|
||||||
|
var AdministratorsGroup = this._marshal.CreatePointer();
|
||||||
|
var admin = false;
|
||||||
|
|
||||||
|
if (this._advapi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||||
|
{
|
||||||
|
var member = this._marshal.CreateInteger();
|
||||||
|
if (this._advapi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||||
|
{
|
||||||
|
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||||
|
}
|
||||||
|
this._advapi.FreeSid(AdministratorsGroup.Deref());
|
||||||
|
}
|
||||||
|
return admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
|
||||||
|
{
|
||||||
|
var buffer = this._marshal.CreatePointer();
|
||||||
|
var bytesReturned = this._marshal.CreateVariable(4);
|
||||||
|
|
||||||
|
if (this._wts.WTSQuerySessionInformationA(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSQuerySessionInformation: ' + this._kernel32.GetLastError.Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
var retVal = buffer.Deref().String;
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(buffer.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Current = function Current(cb)
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
var pinfo = this._marshal.CreatePointer();
|
||||||
|
var count = this._marshal.CreateVariable(4);
|
||||||
|
if (this._wts.WTSEnumerateSessionsA(0, 0, 1, pinfo, count).Val == 0)
|
||||||
|
{
|
||||||
|
throw ('Error calling WTSEnumerateSessionsA: ' + this._kernel32.GetLastError().Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count.toBuffer().readUInt32LE() ; ++i)
|
||||||
|
{
|
||||||
|
var info = pinfo.Deref().Deref(i * (this._marshal.PointerSize == 4 ? 12 : 24), this._marshal.PointerSize == 4 ? 12 : 24);
|
||||||
|
var j = { SessionId: info.toBuffer().readUInt32LE() };
|
||||||
|
j.StationName = info.Deref(this._marshal.PointerSize == 4 ? 4 : 8, this._marshal.PointerSize).Deref().String;
|
||||||
|
j.State = this.SessionStates[info.Deref(this._marshal.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE()];
|
||||||
|
if (j.State == 'Active') {
|
||||||
|
j.Username = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSUserName);
|
||||||
|
j.Domain = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSDomainName);
|
||||||
|
}
|
||||||
|
retVal[j.SessionId] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||||
|
|
||||||
|
Object.defineProperty(retVal, 'Active', { value: showActiveOnly(retVal) });
|
||||||
|
if (cb) { cb(retVal); }
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
|
||||||
|
// from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
|
||||||
|
// on a semaphore for us to return. If we call now, we may deadlock on Windows 7, becuase it will try to notify immediately
|
||||||
|
this.immediate = setImmediate(function (self)
|
||||||
|
{
|
||||||
|
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||||
|
if (self.parent._wts) { 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)
|
||||||
|
{
|
||||||
|
switch(msg.message)
|
||||||
|
{
|
||||||
|
case WM_WTSSESSION_CHANGE:
|
||||||
|
switch(msg.wparam)
|
||||||
|
{
|
||||||
|
case WTS_SESSION_LOCK:
|
||||||
|
this.parent.enumerateUsers().then(function (users)
|
||||||
|
{
|
||||||
|
if (users[msg.lparam]) { this.parent.emit('locked', users[msg.lparam]); }
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case WTS_SESSION_UNLOCK:
|
||||||
|
this.parent.enumerateUsers().then(function (users)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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 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)
|
||||||
|
{
|
||||||
|
this.user_session.emit('changed');
|
||||||
|
});
|
||||||
|
this._users = function _users()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[0]] = tokens[1]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
this._uids = function _uids() {
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines) {
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
this.Self = function Self()
|
||||||
|
{
|
||||||
|
var promise = require('promise');
|
||||||
|
var p = new promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__resolver = res; this.__rejector = rej;
|
||||||
|
this.__child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||||
|
this.__child.promise = this;
|
||||||
|
this.__child.stdout._txt = '';
|
||||||
|
this.__child.stdout.on('data', function (chunk) { this._txt += chunk.toString(); });
|
||||||
|
this.__child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parseInt(this.stdout._txt);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
this.promise.__rejector('invalid uid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = parseInt(this.stdout._txt);
|
||||||
|
this.promise.__resolver(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return (p);
|
||||||
|
};
|
||||||
|
this.Current = function Current(cb)
|
||||||
|
{
|
||||||
|
var retVal = {};
|
||||||
|
retVal._ObjectID = 'UserSession'
|
||||||
|
Object.defineProperty(retVal, '_callback', { value: cb });
|
||||||
|
Object.defineProperty(retVal, '_child', { value: require('child_process').execFile('/usr/bin/last', ['last', '-f', '/var/run/utmp']) });
|
||||||
|
|
||||||
|
retVal._child.Parent = retVal;
|
||||||
|
retVal._child._txt = '';
|
||||||
|
retVal._child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
var lines = this._txt.split('\n');
|
||||||
|
var sessions = [];
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for(var i in lines)
|
||||||
|
{
|
||||||
|
if (lines[i])
|
||||||
|
{
|
||||||
|
var tokens = getTokens(lines[i]);
|
||||||
|
var s = { Username: tokens[0], SessionId: tokens[1] }
|
||||||
|
if (tokens[3].includes('still logged in'))
|
||||||
|
{
|
||||||
|
s.State = 'Active';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.LastActive = tokens[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.push(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessions.pop();
|
||||||
|
|
||||||
|
|
||||||
|
var usernames = {};
|
||||||
|
var promises = [];
|
||||||
|
|
||||||
|
for (var i in sessions)
|
||||||
|
{
|
||||||
|
if (sessions[i].Username != 'reboot')
|
||||||
|
{
|
||||||
|
users[sessions[i].SessionId] = sessions[i];
|
||||||
|
if(usernames[sessions[i].Username] == null)
|
||||||
|
{
|
||||||
|
usernames[sessions[i].Username] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('promise');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||||
|
if (this.Parent._callback) { this.Parent._callback.call(this.Parent, users); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var promise = require('promise');
|
||||||
|
for (var n in usernames)
|
||||||
|
{
|
||||||
|
var p = new promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__username = n;
|
||||||
|
this.__resolver = res; this.__rejector = rej;
|
||||||
|
this.__child = require('child_process').execFile('/usr/bin/id', ['id', '-u', n]);
|
||||||
|
this.__child.promise = this;
|
||||||
|
this.__child.stdout._txt = '';
|
||||||
|
this.__child.stdout.on('data', function (chunk) { this._txt += chunk.toString(); });
|
||||||
|
this.__child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parseInt(this.stdout._txt);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.promise.__rejector('invalid uid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = parseInt(this.stdout._txt);
|
||||||
|
this.promise.__resolver(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
promises.push(p);
|
||||||
|
}
|
||||||
|
promise.all(promises).then(function (plist)
|
||||||
|
{
|
||||||
|
// Done
|
||||||
|
var table = {};
|
||||||
|
for(var i in plist)
|
||||||
|
{
|
||||||
|
table[plist[i].__username] = plist[i]._internal.completedArgs[0];
|
||||||
|
}
|
||||||
|
for(var i in users)
|
||||||
|
{
|
||||||
|
users[i].uid = table[users[i].Username];
|
||||||
|
}
|
||||||
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||||
|
if (retVal._callback) { retVal._callback.call(retVal, users); }
|
||||||
|
}, function (reason)
|
||||||
|
{
|
||||||
|
// Failed
|
||||||
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||||
|
if (retVal._callback) { retVal._callback.call(retVal, users); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
retVal._child.stdout.Parent = retVal._child;
|
||||||
|
retVal._child.stdout.on('data', function (chunk) { this.Parent._txt += chunk.toString(); });
|
||||||
|
|
||||||
|
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._users = function ()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[0]] = tokens[tokens.length - 1]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
|
this._uids = function () {
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[tokens.length - 1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
|
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); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(process.platform == 'linux' || process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
this._self = function _self()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.waitExit();
|
||||||
|
return (parseInt(child.stdout.str));
|
||||||
|
}
|
||||||
|
this.isRoot = function isRoot()
|
||||||
|
{
|
||||||
|
return (this._self() == 0);
|
||||||
|
}
|
||||||
|
this.consoleUid = function consoleUid()
|
||||||
|
{
|
||||||
|
var checkstr = process.platform == 'darwin' ? 'console' : ((process.env['DISPLAY'])?process.env['DISPLAY']:':0')
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('who\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i, j;
|
||||||
|
for (i in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
for (j = 1; j < tokens.length; ++j)
|
||||||
|
{
|
||||||
|
if (tokens[j].length > 0)
|
||||||
|
{
|
||||||
|
return (parseInt(this._users()[tokens[0]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ('nobody logged into console');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
function showActiveOnly(source)
|
||||||
|
{
|
||||||
|
var retVal = [];
|
||||||
|
var unique = {};
|
||||||
|
var usernames = [];
|
||||||
|
var tmp;
|
||||||
|
|
||||||
|
for (var i in source)
|
||||||
|
{
|
||||||
|
if (source[i].State == 'Active')
|
||||||
|
{
|
||||||
|
retVal.push(source[i]);
|
||||||
|
tmp = (source[i].Domain ? (source[i].Domain + '\\') : '') + source[i].Username;
|
||||||
|
if (!unique[tmp]) { unique[tmp] = tmp;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in unique)
|
||||||
|
{
|
||||||
|
usernames.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(retVal, 'usernames', { value: usernames });
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
function getTokens(str)
|
||||||
|
{
|
||||||
|
var columns = [];
|
||||||
|
var i;
|
||||||
|
|
||||||
|
columns.push(str.substring(0, (i=str.indexOf(' '))));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
var status = str.substring(i).trim();
|
||||||
|
columns.push(status);
|
||||||
|
|
||||||
|
return (columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new UserSessions();
|
124
agents-new/modules_meshcore/x/win-message-pump.js
Normal file
124
agents-new/modules_meshcore/x/win-message-pump.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var WH_CALLWNDPROC = 4;
|
||||||
|
var WM_QUIT = 0x0012;
|
||||||
|
|
||||||
|
var GM = require('_GenericMarshal');
|
||||||
|
|
||||||
|
function WindowsMessagePump(options)
|
||||||
|
{
|
||||||
|
this._ObjectID = 'win-message-pump';
|
||||||
|
this._options = options;
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('hwnd');
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
emitterUtils.createEvent('message');
|
||||||
|
emitterUtils.createEvent('exit');
|
||||||
|
|
||||||
|
this._msg = GM.CreateVariable(GM.PointerSize == 4 ? 28 : 48);
|
||||||
|
this._kernel32 = GM.CreateNativeProxy('Kernel32.dll');
|
||||||
|
this._kernel32.mp = this;
|
||||||
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
this._kernel32.CreateMethod('GetModuleHandleA');
|
||||||
|
|
||||||
|
this._user32 = GM.CreateNativeProxy('User32.dll');
|
||||||
|
this._user32.mp = this;
|
||||||
|
this._user32.CreateMethod('GetMessageA');
|
||||||
|
this._user32.CreateMethod('CreateWindowExA');
|
||||||
|
this._user32.CreateMethod('TranslateMessage');
|
||||||
|
this._user32.CreateMethod('DispatchMessageA');
|
||||||
|
this._user32.CreateMethod('RegisterClassExA');
|
||||||
|
this._user32.CreateMethod('DefWindowProcA');
|
||||||
|
this._user32.CreateMethod('PostMessageA');
|
||||||
|
|
||||||
|
|
||||||
|
this.wndclass = GM.CreateVariable(GM.PointerSize == 4 ? 48 : 80);
|
||||||
|
this.wndclass.mp = this;
|
||||||
|
this.wndclass.hinstance = this._kernel32.GetModuleHandleA(0);
|
||||||
|
this.wndclass.cname = GM.CreateVariable('MainWWWClass');
|
||||||
|
this.wndclass.wndproc = GM.GetGenericGlobalCallback(4);
|
||||||
|
this.wndclass.wndproc.mp = this;
|
||||||
|
this.wndclass.toBuffer().writeUInt32LE(this.wndclass._size);
|
||||||
|
this.wndclass.cname.pointerBuffer().copy(this.wndclass.Deref(GM.PointerSize == 4 ? 40 : 64, GM.PointerSize).toBuffer());
|
||||||
|
this.wndclass.wndproc.pointerBuffer().copy(this.wndclass.Deref(8, GM.PointerSize).toBuffer());
|
||||||
|
this.wndclass.hinstance.pointerBuffer().copy(this.wndclass.Deref(GM.PointerSize == 4 ? 20 : 24, GM.PointerSize).toBuffer());
|
||||||
|
this.wndclass.wndproc.on('GlobalCallback', function onWndProc(xhwnd, xmsg, wparam, lparam)
|
||||||
|
{
|
||||||
|
if (this.mp._hwnd != null && this.mp._hwnd.Val == xhwnd.Val)
|
||||||
|
{
|
||||||
|
// This is for us
|
||||||
|
this.mp.emit('message', { message: xmsg.Val, wparam: wparam.Val, lparam: lparam.Val, lparam_hex: lparam.pointerBuffer().toString('hex') });
|
||||||
|
return (this.mp._user32.DefWindowProcA(xhwnd, xmsg, wparam, lparam));
|
||||||
|
}
|
||||||
|
else if(this.mp._hwnd == null && this.CallingThread() == this.mp._user32.RegisterClassExA.async.threadId())
|
||||||
|
{
|
||||||
|
// This message was generated from our CreateWindowExA method
|
||||||
|
return (this.mp._user32.DefWindowProcA(xhwnd, xmsg, wparam, lparam));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._user32.RegisterClassExA.async(this.wndclass).then(function ()
|
||||||
|
{
|
||||||
|
this.nativeProxy.CreateWindowExA.async(this.nativeProxy.RegisterClassExA.async, 0x00000088, this.nativeProxy.mp.wndclass.cname, 0, 0x00800000, 0, 0, 100, 100, 0, 0, 0, 0)
|
||||||
|
.then(function(h)
|
||||||
|
{
|
||||||
|
if (h.Val == 0)
|
||||||
|
{
|
||||||
|
// Error creating hidden window
|
||||||
|
this.nativeProxy.mp.emit('error', 'Error creating hidden window');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.nativeProxy.mp._hwnd = h;
|
||||||
|
this.nativeProxy.mp.emit('hwnd', h);
|
||||||
|
this.nativeProxy.mp._startPump();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this._startPump = function _startPump()
|
||||||
|
{
|
||||||
|
this._user32.GetMessageA.async(this._user32.RegisterClassExA.async, this._msg, this._hwnd, 0, 0).then(function (r)
|
||||||
|
{
|
||||||
|
if(r.Val > 0)
|
||||||
|
{
|
||||||
|
this.nativeProxy.TranslateMessage.async(this.nativeProxy.RegisterClassExA.async, this.nativeProxy.mp._msg).then(function ()
|
||||||
|
{
|
||||||
|
this.nativeProxy.DispatchMessageA.async(this.nativeProxy.RegisterClassExA.async, this.nativeProxy.mp._msg).then(function ()
|
||||||
|
{
|
||||||
|
this.nativeProxy.mp._startPump();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We got a 'QUIT' message
|
||||||
|
delete this.nativeProxy.mp._hwnd;
|
||||||
|
this.nativeProxy.mp.emit('exit', 0);
|
||||||
|
}
|
||||||
|
}, function (err) { this.nativeProxy.mp.stop(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stop = function stop()
|
||||||
|
{
|
||||||
|
if (this._hwnd)
|
||||||
|
{
|
||||||
|
this._user32.PostMessageA(this._hwnd, WM_QUIT, 0, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WindowsMessagePump;
|
218
agents-new/modules_meshcore/x/win-registry.js
Normal file
218
agents-new/modules_meshcore/x/win-registry.js
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var KEY_QUERY_VALUE = 0x0001;
|
||||||
|
var KEY_ENUMERATE_SUB_KEYS = 0x0008;
|
||||||
|
var KEY_WRITE = 0x20006;
|
||||||
|
|
||||||
|
var KEY_DATA_TYPES =
|
||||||
|
{
|
||||||
|
REG_NONE: 0,
|
||||||
|
REG_SZ: 1,
|
||||||
|
REG_EXPAND_SZ: 2,
|
||||||
|
REG_BINARY: 3,
|
||||||
|
REG_DWORD: 4,
|
||||||
|
REG_DWORD_BIG_ENDIAN: 5,
|
||||||
|
REG_LINK: 6,
|
||||||
|
REG_MULTI_SZ: 7,
|
||||||
|
REG_RESOURCE_LIST: 8,
|
||||||
|
REG_FULL_RESOURCE_DESCRIPTOR: 9,
|
||||||
|
REG_RESOURCE_REQUIREMENTS_LIST: 10,
|
||||||
|
REG_QWORD: 11
|
||||||
|
};
|
||||||
|
|
||||||
|
function windows_registry()
|
||||||
|
{
|
||||||
|
this._ObjectId = 'win-registry';
|
||||||
|
this._marshal = require('_GenericMarshal');
|
||||||
|
this._AdvApi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this._AdvApi.CreateMethod('RegCreateKeyExA');
|
||||||
|
this._AdvApi.CreateMethod('RegEnumKeyExA');
|
||||||
|
this._AdvApi.CreateMethod('RegEnumValueA');
|
||||||
|
this._AdvApi.CreateMethod('RegOpenKeyExA');
|
||||||
|
this._AdvApi.CreateMethod('RegQueryInfoKeyA');
|
||||||
|
this._AdvApi.CreateMethod('RegQueryValueExA');
|
||||||
|
this._AdvApi.CreateMethod('RegCloseKey');
|
||||||
|
this._AdvApi.CreateMethod('RegDeleteKeyA');
|
||||||
|
this._AdvApi.CreateMethod('RegDeleteValueA');
|
||||||
|
this._AdvApi.CreateMethod('RegSetValueExA');
|
||||||
|
this.HKEY = { Root: Buffer.from('80000000', 'hex').swap32(), CurrentUser: Buffer.from('80000001', 'hex').swap32(), LocalMachine: Buffer.from('80000002', 'hex').swap32(), Users: Buffer.from('80000003', 'hex').swap32() };
|
||||||
|
|
||||||
|
this.QueryKey = function QueryKey(hkey, path, key)
|
||||||
|
{
|
||||||
|
var err;
|
||||||
|
var h = this._marshal.CreatePointer();
|
||||||
|
var len = this._marshal.CreateVariable(4);
|
||||||
|
var valType = this._marshal.CreateVariable(4);
|
||||||
|
var HK = this._marshal.CreatePointer(hkey);
|
||||||
|
var retVal = null;
|
||||||
|
if (key) { key = this._marshal.CreateVariable(key); }
|
||||||
|
if (!path) { path = ''; }
|
||||||
|
|
||||||
|
|
||||||
|
if ((err = this._AdvApi.RegOpenKeyExA(HK, this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, h).Val) != 0)
|
||||||
|
{
|
||||||
|
throw ('Opening Registry Key: ' + path + ' => Returned Error: ' + err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((path == '' && !key) || !key)
|
||||||
|
{
|
||||||
|
var result = { subkeys: [], values: [] };
|
||||||
|
|
||||||
|
// Enumerate keys
|
||||||
|
var achClass = this._marshal.CreateVariable(1024);
|
||||||
|
var achKey = this._marshal.CreateVariable(1024);
|
||||||
|
var achValue = this._marshal.CreateVariable(32768);
|
||||||
|
var achValueSize = this._marshal.CreateVariable(4);
|
||||||
|
var nameSize = this._marshal.CreateVariable(4);
|
||||||
|
var achClassSize = this._marshal.CreateVariable(4); achClassSize.toBuffer().writeUInt32LE(1024);
|
||||||
|
var numSubKeys = this._marshal.CreateVariable(4);
|
||||||
|
var numValues = this._marshal.CreateVariable(4);
|
||||||
|
var longestSubkeySize = this._marshal.CreateVariable(4);
|
||||||
|
var longestClassString = this._marshal.CreateVariable(4);
|
||||||
|
var longestValueName = this._marshal.CreateVariable(4);
|
||||||
|
var longestValueData = this._marshal.CreateVariable(4);
|
||||||
|
var securityDescriptor = this._marshal.CreateVariable(4);
|
||||||
|
var lastWriteTime = this._marshal.CreateVariable(8);
|
||||||
|
|
||||||
|
retVal = this._AdvApi.RegQueryInfoKeyA(h.Deref(), achClass, achClassSize, 0,
|
||||||
|
numSubKeys, longestSubkeySize, longestClassString, numValues,
|
||||||
|
longestValueName, longestValueData, securityDescriptor, lastWriteTime);
|
||||||
|
if (retVal.Val != 0) { throw ('RegQueryInfoKeyA() returned error: ' + retVal.Val); }
|
||||||
|
for(var i = 0; i < numSubKeys.toBuffer().readUInt32LE(); ++i)
|
||||||
|
{
|
||||||
|
nameSize.toBuffer().writeUInt32LE(1024);
|
||||||
|
retVal = this._AdvApi.RegEnumKeyExA(h.Deref(), i, achKey, nameSize, 0, 0, 0, lastWriteTime);
|
||||||
|
if(retVal.Val == 0)
|
||||||
|
{
|
||||||
|
result.subkeys.push(achKey.String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < numValues.toBuffer().readUInt32LE() ; ++i)
|
||||||
|
{
|
||||||
|
achValueSize.toBuffer().writeUInt32LE(32768);
|
||||||
|
if(this._AdvApi.RegEnumValueA(h.Deref(), i, achValue, achValueSize, 0, 0, 0, 0).Val == 0)
|
||||||
|
{
|
||||||
|
result.values.push(achValue.String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._AdvApi.RegQueryValueExA(h.Deref(), key, 0, 0, 0, len).Val == 0)
|
||||||
|
{
|
||||||
|
var data = this._marshal.CreateVariable(len.toBuffer().readUInt32LE());
|
||||||
|
if (this._AdvApi.RegQueryValueExA(h.Deref(), key, 0, valType, data, len).Val == 0)
|
||||||
|
{
|
||||||
|
switch(valType.toBuffer().readUInt32LE())
|
||||||
|
{
|
||||||
|
case KEY_DATA_TYPES.REG_DWORD:
|
||||||
|
retVal = data.toBuffer().readUInt32LE();
|
||||||
|
break;
|
||||||
|
case KEY_DATA_TYPES.REG_DWORD_BIG_ENDIAN:
|
||||||
|
retVal = data.toBuffer().readUInt32BE();
|
||||||
|
break;
|
||||||
|
case KEY_DATA_TYPES.REG_SZ:
|
||||||
|
retVal = data.String;
|
||||||
|
break;
|
||||||
|
case KEY_DATA_TYPES.REG_BINARY:
|
||||||
|
default:
|
||||||
|
retVal = data.toBuffer();
|
||||||
|
retVal._data = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
throw ('Not Found');
|
||||||
|
}
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.WriteKey = function WriteKey(hkey, path, key, value)
|
||||||
|
{
|
||||||
|
var result;
|
||||||
|
var h = this._marshal.CreatePointer();
|
||||||
|
|
||||||
|
if (this._AdvApi.RegCreateKeyExA(this._marshal.CreatePointer(hkey), this._marshal.CreateVariable(path), 0, 0, 0, KEY_WRITE, 0, h, 0).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Opening Registry Key: ' + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data;
|
||||||
|
var dataType;
|
||||||
|
|
||||||
|
switch(typeof(value))
|
||||||
|
{
|
||||||
|
case 'boolean':
|
||||||
|
dataType = KEY_DATA_TYPES.REG_DWORD;
|
||||||
|
data = this._marshal.CreateVariable(4);
|
||||||
|
data.toBuffer().writeUInt32LE(value ? 1 : 0);
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
dataType = KEY_DATA_TYPES.REG_DWORD;
|
||||||
|
data = this._marshal.CreateVariable(4);
|
||||||
|
data.toBuffer().writeUInt32LE(value);
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
dataType = KEY_DATA_TYPES.REG_SZ;
|
||||||
|
data = this._marshal.CreateVariable(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dataType = KEY_DATA_TYPES.REG_BINARY;
|
||||||
|
data = this._marshal.CreateVariable(value.length);
|
||||||
|
value.copy(data.toBuffer());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._AdvApi.RegSetValueExA(h.Deref(), this._marshal.CreateVariable(key), 0, dataType, data, data._size).Val != 0)
|
||||||
|
{
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
throw ('Error writing reg key: ' + key);
|
||||||
|
}
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
};
|
||||||
|
this.DeleteKey = function DeleteKey(hkey, path, key)
|
||||||
|
{
|
||||||
|
if(!key)
|
||||||
|
{
|
||||||
|
if(this._AdvApi.RegDeleteKeyA(this._marshal.CreatePointer(hkey), this._marshal.CreateVariable(path)).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Deleting Key: ' + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var h = this._marshal.CreatePointer();
|
||||||
|
var result;
|
||||||
|
if (this._AdvApi.RegOpenKeyExA(this._marshal.CreatePointer(hkey), this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE | KEY_WRITE, h).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Opening Registry Key: ' + path);
|
||||||
|
}
|
||||||
|
if ((result = this._AdvApi.RegDeleteValueA(h.Deref(), this._marshal.CreateVariable(key)).Val) != 0)
|
||||||
|
{
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
throw ('Error[' + result + '] Deleting Key: ' + path + '.' + key);
|
||||||
|
}
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new windows_registry();
|
||||||
|
|
466
agents-new/recoverycore.js
Normal file
466
agents-new/recoverycore.js
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
|
||||||
|
var http = require('http');
|
||||||
|
var childProcess = require('child_process');
|
||||||
|
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore Recovery", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
||||||
|
var nextTunnelIndex = 1;
|
||||||
|
var tunnels = {};
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
//attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); });
|
||||||
|
|
||||||
|
function sendConsoleText(msg)
|
||||||
|
{
|
||||||
|
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg });
|
||||||
|
}
|
||||||
|
// Return p number of spaces
|
||||||
|
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
|
||||||
|
|
||||||
|
var path =
|
||||||
|
{
|
||||||
|
join: function ()
|
||||||
|
{
|
||||||
|
var x = [];
|
||||||
|
for (var i in arguments)
|
||||||
|
{
|
||||||
|
var w = arguments[i];
|
||||||
|
if (w != null)
|
||||||
|
{
|
||||||
|
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
|
||||||
|
}
|
||||||
|
x.push(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x.length == 0) return '/';
|
||||||
|
return x.join('/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Convert an object to string with all functions
|
||||||
|
function objToString(x, p, pad, ret) {
|
||||||
|
if (ret == undefined) ret = '';
|
||||||
|
if (p == undefined) p = 0;
|
||||||
|
if (x == null) { return '[null]'; }
|
||||||
|
if (p > 8) { return '[...]'; }
|
||||||
|
if (x == undefined) { return '[undefined]'; }
|
||||||
|
if (typeof x == 'string') { if (p == 0) return x; return '"' + x + '"'; }
|
||||||
|
if (typeof x == 'buffer') { return '[buffer]'; }
|
||||||
|
if (typeof x != 'object') { return x; }
|
||||||
|
var r = '{' + (ret ? '\r\n' : ' ');
|
||||||
|
for (var i in x) { if (i != '_ObjectID') { r += (addPad(p + 2, pad) + i + ': ' + objToString(x[i], p + 2, pad, ret) + (ret ? '\r\n' : ' ')); } }
|
||||||
|
return r + addPad(p, pad) + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split a string taking into account the quoats. Used for command line parsing
|
||||||
|
function splitArgs(str)
|
||||||
|
{
|
||||||
|
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
|
||||||
|
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
|
||||||
|
return myArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse arguments string array into an object
|
||||||
|
function parseArgs(argv)
|
||||||
|
{
|
||||||
|
var results = { '_': [] }, current = null;
|
||||||
|
for (var i = 1, len = argv.length; i < len; i++) {
|
||||||
|
var x = argv[i];
|
||||||
|
if (x.length > 2 && x[0] == '-' && x[1] == '-') {
|
||||||
|
if (current != null) { results[current] = true; }
|
||||||
|
current = x.substring(2);
|
||||||
|
} else {
|
||||||
|
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current != null) { results[current] = true; }
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
// Get server target url with a custom path
|
||||||
|
function getServerTargetUrl(path)
|
||||||
|
{
|
||||||
|
var x = require('MeshAgent').ServerUrl;
|
||||||
|
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
|
||||||
|
if (x == null) { return null; }
|
||||||
|
if (path == null) { path = ''; }
|
||||||
|
x = http.parseUri(x);
|
||||||
|
if (x == null) return null;
|
||||||
|
return x.protocol + '//' + x.host + ':' + x.port + '/' + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get server url. If the url starts with "*/..." change it, it not use the url as is.
|
||||||
|
function getServerTargetUrlEx(url)
|
||||||
|
{
|
||||||
|
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
require('MeshAgent').on('Connected', function ()
|
||||||
|
{
|
||||||
|
require('os').name().then(function (v)
|
||||||
|
{
|
||||||
|
sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
|
||||||
|
require('MeshAgent').SendCommand(meshCoreObj);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tunnel callback operations
|
||||||
|
function onTunnelUpgrade(response, s, head) {
|
||||||
|
this.s = s;
|
||||||
|
s.httprequest = this;
|
||||||
|
s.end = onTunnelClosed;
|
||||||
|
s.tunnel = this;
|
||||||
|
|
||||||
|
//sendConsoleText('onTunnelUpgrade');
|
||||||
|
|
||||||
|
if (this.tcpport != null) {
|
||||||
|
// This is a TCP relay connection, pause now and try to connect to the target.
|
||||||
|
s.pause();
|
||||||
|
s.data = onTcpRelayServerTunnelData;
|
||||||
|
var connectionOptions = { port: parseInt(this.tcpport) };
|
||||||
|
if (this.tcpaddr != null) { connectionOptions.host = this.tcpaddr; } else { connectionOptions.host = '127.0.0.1'; }
|
||||||
|
s.tcprelay = net.createConnection(connectionOptions, onTcpRelayTargetTunnelConnect);
|
||||||
|
s.tcprelay.peerindex = this.index;
|
||||||
|
} else {
|
||||||
|
// This is a normal connect for KVM/Terminal/Files
|
||||||
|
s.data = onTunnelData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require('MeshAgent').AddCommandHandler(function (data)
|
||||||
|
{
|
||||||
|
if (typeof data == 'object')
|
||||||
|
{
|
||||||
|
// If this is a console command, parse it and call the console handler
|
||||||
|
switch (data.action)
|
||||||
|
{
|
||||||
|
case 'msg':
|
||||||
|
{
|
||||||
|
switch (data.type)
|
||||||
|
{
|
||||||
|
case 'console': { // Process a console command
|
||||||
|
if (data.value && data.sessionid)
|
||||||
|
{
|
||||||
|
var args = splitArgs(data.value);
|
||||||
|
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'tunnel':
|
||||||
|
{
|
||||||
|
if (data.value != null) { // Process a new tunnel connection request
|
||||||
|
// Create a new tunnel object
|
||||||
|
var xurl = getServerTargetUrlEx(data.value);
|
||||||
|
if (xurl != null) {
|
||||||
|
var woptions = http.parseUri(xurl);
|
||||||
|
woptions.rejectUnauthorized = 0;
|
||||||
|
//sendConsoleText(JSON.stringify(woptions));
|
||||||
|
var tunnel = http.request(woptions);
|
||||||
|
tunnel.on('upgrade', function (response, s, head)
|
||||||
|
{
|
||||||
|
this.s = s;
|
||||||
|
s.httprequest = this;
|
||||||
|
s.tunnel = this;
|
||||||
|
s.on('end', function ()
|
||||||
|
{
|
||||||
|
if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
|
||||||
|
|
||||||
|
// If there is a upload or download active on this connection, close the file
|
||||||
|
if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||||
|
if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
|
||||||
|
|
||||||
|
|
||||||
|
//sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
|
||||||
|
delete tunnels[this.httprequest.index];
|
||||||
|
|
||||||
|
// Clean up WebSocket
|
||||||
|
this.removeAllListeners('data');
|
||||||
|
});
|
||||||
|
s.on('data', function (data)
|
||||||
|
{
|
||||||
|
// If this is upload data, save it to file
|
||||||
|
if (this.httprequest.uploadFile)
|
||||||
|
{
|
||||||
|
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
|
||||||
|
this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.httprequest.state == 0) {
|
||||||
|
// Check if this is a relay connection
|
||||||
|
if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
|
||||||
|
} else {
|
||||||
|
// Handle tunnel data
|
||||||
|
if (this.httprequest.protocol == 0)
|
||||||
|
{
|
||||||
|
// Take a look at the protocol
|
||||||
|
this.httprequest.protocol = parseInt(data);
|
||||||
|
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
|
||||||
|
if (this.httprequest.protocol == 1)
|
||||||
|
{
|
||||||
|
// Remote terminal using native pipes
|
||||||
|
if (process.platform == "win32")
|
||||||
|
{
|
||||||
|
this.httprequest._term = require('win-terminal').Start(80, 25);
|
||||||
|
this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
|
||||||
|
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
|
||||||
|
this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
|
||||||
|
this.httprequest.process.tunnel = this;
|
||||||
|
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
|
||||||
|
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
|
||||||
|
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||||
|
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||||
|
this.prependListener('end', function () { this.httprequest.process.kill(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on('end', function () {
|
||||||
|
if (process.platform == "win32")
|
||||||
|
{
|
||||||
|
// Unpipe the web socket
|
||||||
|
this.unpipe(this.httprequest._term);
|
||||||
|
this.httprequest._term.unpipe(this);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
this.httprequest._term.end();
|
||||||
|
this.httprequest._term = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.httprequest.protocol == 5)
|
||||||
|
{
|
||||||
|
// Process files commands
|
||||||
|
var cmd = null;
|
||||||
|
try { cmd = JSON.parse(data); } catch (e) { };
|
||||||
|
if (cmd == null) { return; }
|
||||||
|
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
|
||||||
|
if (cmd.action == undefined) { return; }
|
||||||
|
console.log('action: ', cmd.action);
|
||||||
|
|
||||||
|
//sendConsoleText('CMD: ' + JSON.stringify(cmd));
|
||||||
|
|
||||||
|
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
|
||||||
|
//console.log(objToString(cmd, 0, ' '));
|
||||||
|
switch (cmd.action)
|
||||||
|
{
|
||||||
|
case 'ls':
|
||||||
|
// Send the folder content to the browser
|
||||||
|
var response = getDirectoryInfo(cmd.path);
|
||||||
|
if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
|
||||||
|
this.write(new Buffer(JSON.stringify(response)));
|
||||||
|
break;
|
||||||
|
case 'mkdir': {
|
||||||
|
// Create a new empty folder
|
||||||
|
fs.mkdirSync(cmd.path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rm': {
|
||||||
|
// Delete, possibly recursive delete
|
||||||
|
for (var i in cmd.delfiles)
|
||||||
|
{
|
||||||
|
try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'rename': {
|
||||||
|
// Rename a file or folder
|
||||||
|
var oldfullpath = path.join(cmd.path, cmd.oldname);
|
||||||
|
var newfullpath = path.join(cmd.path, cmd.newname);
|
||||||
|
try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'upload': {
|
||||||
|
// Upload a file, browser to agent
|
||||||
|
if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
|
||||||
|
if (cmd.path == undefined) break;
|
||||||
|
var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path;
|
||||||
|
try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
|
||||||
|
this.httprequest.uploadFileid = cmd.reqid;
|
||||||
|
if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'copy': {
|
||||||
|
// Copy a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'move': {
|
||||||
|
// Move a bunch of files from scpath to dspath
|
||||||
|
for (var i in cmd.names) {
|
||||||
|
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
|
||||||
|
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
|
||||||
|
tunnel.sessionid = data.sessionid;
|
||||||
|
tunnel.rights = data.rights;
|
||||||
|
tunnel.state = 0;
|
||||||
|
tunnel.url = xurl;
|
||||||
|
tunnel.protocol = 0;
|
||||||
|
tunnel.tcpaddr = data.tcpaddr;
|
||||||
|
tunnel.tcpport = data.tcpport;
|
||||||
|
tunnel.end();
|
||||||
|
// Put the tunnel in the tunnels list
|
||||||
|
var index = nextTunnelIndex++;
|
||||||
|
tunnel.index = index;
|
||||||
|
tunnels[index] = tunnel;
|
||||||
|
|
||||||
|
//sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown action, ignore it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Unknown action, ignore it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function processConsoleCommand(cmd, args, rights, sessionid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = null;
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case 'help':
|
||||||
|
response = 'Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'osinfo': { // Return the operating system information
|
||||||
|
var i = 1;
|
||||||
|
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
|
||||||
|
for (var j = 0; j < i; j++) {
|
||||||
|
var pr = require('os').name();
|
||||||
|
pr.sessionid = sessionid;
|
||||||
|
pr.then(function (v) { sendConsoleText("OS: " + v, this.sessionid); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbkeys': { // Return all data store keys
|
||||||
|
response = JSON.stringify(db.Keys);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbget': { // Return the data store value for a given key
|
||||||
|
if (db == null) { response = 'Database not accessible.'; break; }
|
||||||
|
if (args['_'].length != 1) {
|
||||||
|
response = 'Proper usage: dbget (key)'; // Display the value for a given database key
|
||||||
|
} else {
|
||||||
|
response = db.Get(args['_'][0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbset': { // Set a data store key and value pair
|
||||||
|
if (db == null) { response = 'Database not accessible.'; break; }
|
||||||
|
if (args['_'].length != 2) {
|
||||||
|
response = 'Proper usage: dbset (key) (value)'; // Set a database key
|
||||||
|
} else {
|
||||||
|
var r = db.Put(args['_'][0], args['_'][1]);
|
||||||
|
response = 'Key set: ' + r;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'dbcompact': { // Compact the data store
|
||||||
|
if (db == null) { response = 'Database not accessible.'; break; }
|
||||||
|
var r = db.Compact();
|
||||||
|
response = 'Database compacted: ' + r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'tunnels': { // Show the list of current tunnels
|
||||||
|
response = '';
|
||||||
|
for (var i in tunnels) { response += 'Tunnel #' + i + ', ' + tunnels[i].url + '\r\n'; }
|
||||||
|
if (response == '') { response = 'No websocket sessions.'; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'netinfo': { // Show network interface information
|
||||||
|
//response = objToString(mesh.NetInfo, 0, ' ');
|
||||||
|
var interfaces = require('os').networkInterfaces();
|
||||||
|
response = objToString(interfaces, 0, ' ', true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { // This is an unknown command, return an error message
|
||||||
|
response = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); }
|
||||||
|
if (response != null) { sendConsoleText(response, sessionid); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a formated response for a given directory path
|
||||||
|
function getDirectoryInfo(reqpath)
|
||||||
|
{
|
||||||
|
var response = { path: reqpath, dir: [] };
|
||||||
|
if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
|
||||||
|
// List all the drives in the root, or the root itself
|
||||||
|
var results = null;
|
||||||
|
try { results = fs.readDrivesSync(); } catch (e) { } // TODO: Anyway to get drive total size and free space? Could draw a progress bar.
|
||||||
|
if (results != null) {
|
||||||
|
for (var i = 0; i < results.length; ++i) {
|
||||||
|
var drive = { n: results[i].name, t: 1 };
|
||||||
|
if (results[i].type == 'REMOVABLE') { drive.dt = 'removable'; } // TODO: See if this is USB/CDROM or something else, we can draw icons.
|
||||||
|
response.dir.push(drive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// List all the files and folders in this path
|
||||||
|
if (reqpath == '') { reqpath = '/'; }
|
||||||
|
var results = null, xpath = path.join(reqpath, '*');
|
||||||
|
//if (process.platform == "win32") { xpath = xpath.split('/').join('\\'); }
|
||||||
|
try { results = fs.readdirSync(xpath); } catch (e) { }
|
||||||
|
if (results != null) {
|
||||||
|
for (var i = 0; i < results.length; ++i) {
|
||||||
|
if ((results[i] != '.') && (results[i] != '..')) {
|
||||||
|
var stat = null, p = path.join(reqpath, results[i]);
|
||||||
|
//if (process.platform == "win32") { p = p.split('/').join('\\'); }
|
||||||
|
try { stat = fs.statSync(p); } catch (e) { } // TODO: Get file size/date
|
||||||
|
if ((stat != null) && (stat != undefined)) {
|
||||||
|
if (stat.isDirectory() == true) {
|
||||||
|
response.dir.push({ n: results[i], t: 2, d: stat.mtime });
|
||||||
|
} else {
|
||||||
|
response.dir.push({ n: results[i], t: 3, s: stat.size, d: stat.mtime });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
// Delete a directory with a files and directories within it
|
||||||
|
function deleteFolderRecursive(path, rec) {
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
if (rec == true) {
|
||||||
|
fs.readdirSync(path.join(path, '*')).forEach(function (file, index) {
|
||||||
|
var curPath = path.join(path, file);
|
||||||
|
if (fs.statSync(curPath).isDirectory()) { // recurse
|
||||||
|
deleteFolderRecursive(curPath, true);
|
||||||
|
} else { // delete file
|
||||||
|
fs.unlinkSync(curPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fs.unlinkSync(path);
|
||||||
|
}
|
||||||
|
};
|
157
agents-new/testsuite.js
Normal file
157
agents-new/testsuite.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Polyfill String.endsWith
|
||||||
|
if (!String.prototype.endsWith) {
|
||||||
|
String.prototype.endsWith = function (searchString, position) {
|
||||||
|
var subjectString = this.toString();
|
||||||
|
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { position = subjectString.length; }
|
||||||
|
position -= searchString.length;
|
||||||
|
var lastIndex = subjectString.lastIndexOf(searchString, position);
|
||||||
|
return lastIndex !== -1 && lastIndex === position;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace a string with a number if the string is an exact number
|
||||||
|
function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) == x)) { x = parseInt(x); } return x; }
|
||||||
|
|
||||||
|
// Convert decimal to hex
|
||||||
|
function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }
|
||||||
|
|
||||||
|
// Convert a raw string to a hex string
|
||||||
|
function rstr2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); } return r; }
|
||||||
|
|
||||||
|
// Convert a buffer into a string
|
||||||
|
function buf2rstr(buf) { var r = ''; for (var i = 0; i < buf.length; i++) { r += String.fromCharCode(buf[i]); } return r; }
|
||||||
|
|
||||||
|
// Convert a hex string to a raw string // TODO: Do this using Buffer(), will be MUCH faster
|
||||||
|
function hex2rstr(d) {
|
||||||
|
if (typeof d != "string" || d.length == 0) return '';
|
||||||
|
var r = '', m = ('' + d).match(/../g), t;
|
||||||
|
while (t = m.shift()) r += String.fromCharCode('0x' + t);
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert an object to string with all functions
|
||||||
|
function objToString(x, p, ret) {
|
||||||
|
if (ret == undefined) ret = '';
|
||||||
|
if (p == undefined) p = 0;
|
||||||
|
if (x == null) { return '[null]'; }
|
||||||
|
if (p > 8) { return '[...]'; }
|
||||||
|
if (x == undefined) { return '[undefined]'; }
|
||||||
|
if (typeof x == 'string') { if (p == 0) return x; return '"' + x + '"'; }
|
||||||
|
if (typeof x == 'buffer') { return '[buffer]'; }
|
||||||
|
if (typeof x != 'object') { return x; }
|
||||||
|
var r = '{' + (ret ? '\r\n' : ' ');
|
||||||
|
for (var i in x) { r += (addPad(p + 2, ret) + i + ': ' + objToString(x[i], p + 2, ret) + (ret ? '\r\n' : ' ')); }
|
||||||
|
return r + addPad(p, ret) + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return p number of spaces
|
||||||
|
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
|
||||||
|
|
||||||
|
// Split a string taking into account the quoats. Used for command line parsing
|
||||||
|
function splitArgs(str) {
|
||||||
|
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
|
||||||
|
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
|
||||||
|
return myArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse arguments string array into an object
|
||||||
|
function parseArgs(argv) {
|
||||||
|
var results = { '_': [] }, current = null;
|
||||||
|
for (var i = 1, len = argv.length; i < len; i++) {
|
||||||
|
var x = argv[i];
|
||||||
|
if (x.length > 2 && x[0] == '-' && x[1] == '-') {
|
||||||
|
if (current != null) { results[current] = true; }
|
||||||
|
current = x.substring(2);
|
||||||
|
} else {
|
||||||
|
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current != null) { results[current] = true; }
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parge a URL string into an options object
|
||||||
|
function parseUrl(url) {
|
||||||
|
var x = url.split('/');
|
||||||
|
if (x.length < 4) return null;
|
||||||
|
var y = x[2].split(':');
|
||||||
|
var options = {};
|
||||||
|
var options = { protocol: x[0], hostname: y[0], path: '/' + x.splice(3).join('/') };
|
||||||
|
if (y.length == 1) { options.port = ((x[0] == 'https:') || (x[0] == 'wss:')) ? 443 : 80; } else { options.port = parseInt(y[1]); }
|
||||||
|
if (isNaN(options.port) == true) return null;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(objToString(db2, 2, ' '));
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: Fix this to use the event emitor
|
||||||
|
// TODO: Add SHA256 sync
|
||||||
|
console.log('--- Test 1: SHA256 hashing ---');
|
||||||
|
var sha256 = require('SHA256Stream');
|
||||||
|
sha256.hashString = function (x) { if (x == '81B637D8FCD2C6DA6359E6963113A1170DE795E4B725B84D1E0B4CFD9EC58CE9') { console.log('Test 1 - OK: ' + x); } else { console.log('Test 1 - FAIL: ' + x); } };
|
||||||
|
sha256.write('bob');
|
||||||
|
sha256.end();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// FAIL!!!!!!!!!
|
||||||
|
var sha256x = require('SHA256Stream');
|
||||||
|
sha256x.hashString = function (x) { if (x == '81B637D8FCD2C6DA6359E6963113A1170DE795E4B725B84D1E0B4CFD9EC58CE9') { console.log('Test 1 - OK: ' + x); } else { console.log('Test 1 - FAIL: ' + x); } };
|
||||||
|
sha256x.write('bob');
|
||||||
|
sha256x.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
console.log('--- Test 2: Database ---');
|
||||||
|
var db = require('SimpleDataStore').Create('TestSuite.db');
|
||||||
|
var sha256 = require('SHA256Stream');
|
||||||
|
|
||||||
|
// Write a pile of hashes to the DB
|
||||||
|
sha256.hashString = function (x) { db.Put(x.substring(0, 16), x.substring(16)); console.log('ADD: ' + x.substring(0, 16) + ': ' + x.substring(16)); };
|
||||||
|
for (var i = 0; i < 10; i++) { console.log(i); sha256.write('A' + i); sha256.end(); }
|
||||||
|
|
||||||
|
// Compact plenty of times
|
||||||
|
for (var i = 0; i < 10; i++) { console.log(i); db.Compact(); }
|
||||||
|
|
||||||
|
// Check all the hashes
|
||||||
|
sha256.hashString = function (x) {
|
||||||
|
var r = db.Get(x.substring(0, 16));
|
||||||
|
console.log('GET: ' + x.substring(0, 16) + ': ' + r);
|
||||||
|
if (r != x.substring(16)) { console.log('FAILED ' + x.substring(0, 16) + ': ' + x.substring(16) + ' != ' + r); }
|
||||||
|
//db.Put(x.substring(0, 16), '');
|
||||||
|
};
|
||||||
|
for (var i = 0; i < 10; i++) { console.log(i); sha256.write('A' + i); sha256.end(); }
|
||||||
|
console.log('Test 2 - Completed.');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
console.log('--- Test 3: Files ---');
|
||||||
|
var r, fs = require('fs');
|
||||||
|
//console.log(objToString(fs, 2, ' '));
|
||||||
|
r = fs.mkdirSync('TestSuite-123');
|
||||||
|
r = fs.renameSync('TestSuite-123', 'TestSuite-1234');
|
||||||
|
console.log(r);
|
||||||
|
r = fs.unlinkSync('TestSuite-1234');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('--- Tests Completed ---');
|
||||||
|
process.exit(2);
|
67
agents-new/tinycore.js
Normal file
67
agents-new/tinycore.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018-2019 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 createMeshCore(agent) {
|
||||||
|
var obj = {};
|
||||||
|
|
||||||
|
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
||||||
|
obj.meshCoreInfo = "TinyCore v1";
|
||||||
|
|
||||||
|
if (agent == null) {
|
||||||
|
// If we are running in Duktape, agent will be null
|
||||||
|
var mesh = require('MeshAgent');
|
||||||
|
} else {
|
||||||
|
// Running in nodejs
|
||||||
|
var mesh = agent.getMeshApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle a mesh agent command
|
||||||
|
function handleServerCommand(data) {
|
||||||
|
if ((typeof data == 'object') && (data.action == 'msg') && (data.type == 'console') && data.value && data.sessionid) {
|
||||||
|
mesh.SendCommand({ "action": "msg", "type": "console", "value": "Tiny core: " + data.value, "sessionid": data.sessionid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the server connection state changes
|
||||||
|
function handleServerConnection(state) {
|
||||||
|
if (state == 1) { mesh.SendCommand({ "action": "coreinfo", "value": obj.meshCoreInfo }); } // Server connected, send mesh core information
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.start = function() {
|
||||||
|
// Hook up mesh agent events
|
||||||
|
mesh.AddCommandHandler(handleServerCommand);
|
||||||
|
mesh.AddConnectHandler(handleServerConnection);
|
||||||
|
mesh.SendCommand({ "action": "coreinfo", "value": obj.meshCoreInfo }); // TODO: Check if connected before sending
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.stop = function() {
|
||||||
|
mesh.AddCommandHandler(null);
|
||||||
|
mesh.AddConnectHandler(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
var xexports = 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
|
||||||
|
createMeshCore().start(null);
|
||||||
|
}
|
@ -1094,6 +1094,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
if ((command.caps != null) && (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; } // Don't save this as an event to the db.
|
if ((command.caps != null) && (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; } // Don't save this as an event to the db.
|
||||||
if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; } // Allow Javascript on the agent to change all capabilities except console and javascript support, Don't save this as an event to the db.
|
if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; } // Allow Javascript on the agent to change all capabilities except console and javascript support, Don't save this as an event to the db.
|
||||||
if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; changes.push('os desc'); } // Don't save this as an event to the db.
|
if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; changes.push('os desc'); } // Don't save this as an event to the db.
|
||||||
|
if (device.ip != obj.remoteaddr) { device.ip = obj.remoteaddr; change = 1; }
|
||||||
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)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; log = 1; }
|
if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; log = 1; }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.3.0-i",
|
"version": "0.3.0-k",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -922,7 +922,7 @@
|
|||||||
QV('p13AutoConnect', debugmode); // Files
|
QV('p13AutoConnect', debugmode); // Files
|
||||||
QV('autoconnectbutton2', debugmode); // Terminal
|
QV('autoconnectbutton2', debugmode); // Terminal
|
||||||
QV('autoconnectbutton1', debugmode); // Desktop
|
QV('autoconnectbutton1', debugmode); // Desktop
|
||||||
QV('DeskClip', debugmode); // Clipboard feature, not completed so show in in debug mode only.
|
//QV('DeskClip', debugmode); // Clipboard feature, not completed so show in in debug mode only.
|
||||||
|
|
||||||
toggleFullScreen();
|
toggleFullScreen();
|
||||||
|
|
||||||
@ -2050,34 +2050,42 @@
|
|||||||
var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
|
var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
|
||||||
deviceBoxWidth = 301 + Math.floor((totalDeviceViewWidth - (deviceBoxWidth * 301)) / deviceBoxWidth);
|
deviceBoxWidth = 301 + Math.floor((totalDeviceViewWidth - (deviceBoxWidth * 301)) / deviceBoxWidth);
|
||||||
|
|
||||||
|
if (view == 2) {
|
||||||
|
r += '<table style=width:100%;margin-top:4px cellpadding=0 cellspacing=0><th style=color:gray><th style=color:gray;width:120px>User<th style=color:gray;width:120px>Address<th style=color:gray;width:100px>Connectivity'; //<th style=color:gray;width:100px>State';
|
||||||
|
}
|
||||||
|
|
||||||
// Go thru the list of nodes and display them
|
// Go thru the list of nodes and display them
|
||||||
for (var i in nodes) {
|
for (var i in nodes) {
|
||||||
if (nodes[i].v == false) continue;
|
var node = nodes[i];
|
||||||
var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links['user/' + domain + '/' + userinfo.name.toLowerCase()];
|
if (node.v == false) continue;
|
||||||
|
var mesh2 = meshes[node.meshid], meshlinks = mesh2.links['user/' + domain + '/' + userinfo.name.toLowerCase()];
|
||||||
if (meshlinks == null) continue;
|
if (meshlinks == null) continue;
|
||||||
var meshrights = meshlinks.rights;
|
var meshrights = meshlinks.rights;
|
||||||
if ((view == 3) && (mesh2.mtype == 1)) continue;
|
if ((view == 3) && (mesh2.mtype == 1)) continue;
|
||||||
if (sort == 0) {
|
if (sort == 0) {
|
||||||
// Mesh header
|
// Mesh header
|
||||||
if (nodes[i].meshid != current) {
|
if (node.meshid != current) {
|
||||||
deviceHeaderSet();
|
deviceHeaderSet();
|
||||||
var extra = '';
|
var extra = '';
|
||||||
if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span class=devHeaderx>, Intel® AMT only</span>'; }
|
if (view == 2) { r += '<tr><td colspan=5>'; }
|
||||||
|
if (meshes[node.meshid].mtype == 1) { extra = '<span class=devHeaderx>, Intel® AMT only</span>'; }
|
||||||
if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||||||
|
if (view == 2) { r += '<div>'; }
|
||||||
r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
|
r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
|
||||||
r += getMeshActions(mesh2, meshrights);
|
r += getMeshActions(mesh2, meshrights);
|
||||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span></div>';
|
r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + node.meshid + '")>' + EscapeHtml(meshes[node.meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span></div>';
|
||||||
current = nodes[i].meshid;
|
if (view == 2) { r += '</div>'; }
|
||||||
|
current = node.meshid;
|
||||||
displayedMeshes[current] = 1;
|
displayedMeshes[current] = 1;
|
||||||
c = 0;
|
c = 0;
|
||||||
}
|
}
|
||||||
} else if (sort == 1) {
|
} else if (sort == 1) {
|
||||||
// Power header
|
// Power header
|
||||||
var pwr = nodes[i].pwr?nodes[i].pwr:0;
|
var pwr = node.pwr?node.pwr:0;
|
||||||
if (pwr !== current) {
|
if (pwr !== current) {
|
||||||
deviceHeaderSet();
|
deviceHeaderSet();
|
||||||
if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||||||
r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></div>';
|
r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(node.pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></div>';
|
||||||
current = pwr;
|
current = pwr;
|
||||||
c = 0;
|
c = 0;
|
||||||
}
|
}
|
||||||
@ -2087,41 +2095,52 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
var title = EscapeHtml(nodes[i].name);
|
var title = EscapeHtml(node.name);
|
||||||
if (title.length == 0) { title = '<i>None</i>'; }
|
if (title.length == 0) { title = '<i>None</i>'; }
|
||||||
if ((nodes[i].rname != null) && (nodes[i].rname.length > 0)) { title += " / " + EscapeHtml(nodes[i].rname); }
|
if ((node.rname != null) && (node.rname.length > 0)) { title += " / " + EscapeHtml(node.rname); }
|
||||||
var name = EscapeHtml(nodes[i].name);
|
var name = EscapeHtml(node.name);
|
||||||
if (showRealNames == true && nodes[i].rname != null) name = EscapeHtml(nodes[i].rname);
|
if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
|
||||||
if (name.length == 0) { name = '<i>None</i>'; }
|
if (name.length == 0) { name = '<i>None</i>'; }
|
||||||
|
|
||||||
// Node
|
// Node
|
||||||
var icon = nodes[i].icon;
|
var icon = node.icon;
|
||||||
var nodestate = NodeStateStr(nodes[i]);
|
if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
|
||||||
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
|
|
||||||
if (view == 1) {
|
if (view == 1) {
|
||||||
r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + nodestate + '</div></div><div class=g2></div></div></div></div>';
|
r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div></div>';
|
||||||
} else if (view == 2) {
|
} else if (view == 2) {
|
||||||
|
var states = [];
|
||||||
|
if (node.conn) {
|
||||||
|
if ((node.conn & 1) != 0) { states.push('<span title="Mesh agent is connected and ready for use.">Agent</span>'); }
|
||||||
|
if ((node.conn & 2) != 0) { states.push('<span title="Intel® AMT CIRA is connected and ready for use.">CIRA</span>'); }
|
||||||
|
else if ((node.conn & 4) != 0) { states.push('<span title="Intel® AMT is routable.">AMT</span>'); }
|
||||||
|
if ((node.conn & 8) != 0) { states.push('<span title="Mesh agent is reachable using another agent as relay.">Relay</span>'); }
|
||||||
|
}
|
||||||
r += '<tr><td><div id=devs class=bar18 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium>';
|
r += '<tr><td><div id=devs class=bar18 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium>';
|
||||||
r += '<div style=width:22px;float:left;background-color:white><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div>';
|
r += '<div style=width:22px;float:left;background-color:white><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
|
||||||
r += '<div style=float:left;height:18px;width:18px;background-color:white onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)><div class=j' + icon + ' style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
|
r += '<div style=float:left;height:18px;width:18px;background-color:white onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class=j' + icon + ' style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
|
||||||
r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
|
r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
|
||||||
r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)><span style=float:right>' + nodestate + '</span><span style=width:300px>' + name + '</span></div></div></td></tr>';
|
r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + node._id + '\',null,null,event)><span style=width:300px>' + name + '</span></div></div></td>';
|
||||||
} else if ((view == 3) && (nodes[i].conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((nodes[i].agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
|
r += '<td style=text-align:center>' + getUserShortStr(node);
|
||||||
if ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodes[i]._id) >= 0)) {
|
r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
|
||||||
r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\',11,null,event)>';
|
r += '<td style=text-align:center>' + states.join(' + ');
|
||||||
//r += '<input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox style=float:left>';
|
//r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
|
||||||
|
r += '</tr>';
|
||||||
|
} else if ((view == 3) && (node.conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((node.agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
|
||||||
|
if ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0)) {
|
||||||
|
r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + node._id + '\',11,null,event)>';
|
||||||
|
//r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
|
||||||
r += '<div class="j' + icon + '" style=width:16px;float:left></div> ' + name + '</div>';
|
r += '<div class="j' + icon + '" style=width:16px;float:left></div> ' + name + '</div>';
|
||||||
r += '<span onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)></span><div id=xkvmid_' + nodes[i]._id.split('/')[2] + '><div id=skvmid_' + nodes[i]._id.split('/')[2] + ' style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + nodes[i]._id + '\')>Disconnected</div></div>';
|
r += '<span onclick=gotoDevice(\'' + node._id + '\',null,null,event)></span><div id=xkvmid_' + node._id.split('/')[2] + '><div id=skvmid_' + node._id.split('/')[2] + ' style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + node._id + '\')>Disconnected</div></div>';
|
||||||
r += '</div>';
|
r += '</div>';
|
||||||
kvmDivs.push(nodes[i]._id);
|
kvmDivs.push(node._id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are displaying devices by group, put the device in the right group.
|
// If we are displaying devices by group, put the device in the right group.
|
||||||
if ((sort == 3) && (r != '')) {
|
if ((sort == 3) && (r != '')) {
|
||||||
if (nodes[i].tags) {
|
if (node.tags) {
|
||||||
for (var j in nodes[i].tags) {
|
for (var j in node.tags) {
|
||||||
var tag = nodes[i].tags[j];
|
var tag = node.tags[j];
|
||||||
if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
|
if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
|
||||||
if (view == 3) break;
|
if (view == 3) break;
|
||||||
}
|
}
|
||||||
@ -2130,7 +2149,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
deviceHeaderTotal++;
|
deviceHeaderTotal++;
|
||||||
if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
|
if (typeof deviceHeaderCount[node.state] == 'undefined') { deviceHeaderCount[node.state] = 1; } else { deviceHeaderCount[node.state]++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// If displaying devices by groups, sort the group names and display the devices.
|
// If displaying devices by groups, sort the group names and display the devices.
|
||||||
@ -2278,6 +2297,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUserShortStr(node) {
|
||||||
|
if (node == null || node.users == null || node.users.length == 0) return '';
|
||||||
|
if (node.users.length > 1) { return '<span title="' + EscapeHtml(node.users.join(', ')) + '">' + node.users.length + ' users</span>'; }
|
||||||
|
var u = node.users[0], su = u, i = u.indexOf('\\');
|
||||||
|
if (i > 0) { su = u.substring(i + 1); }
|
||||||
|
su = EscapeHtml(su);
|
||||||
|
if (su.length > 15) { su = su.substring(0, 14) + '…'; }
|
||||||
|
return '<span title="' + EscapeHtml(u) + '">' + su + '</span>';
|
||||||
|
}
|
||||||
|
|
||||||
function autoConnectDesktops() { if (Q('autoConnectDesktopCheckbox').checked == true) { connectAllKvmFunction(); } }
|
function autoConnectDesktops() { if (Q('autoConnectDesktopCheckbox').checked == true) { connectAllKvmFunction(); } }
|
||||||
function connectAllKvmFunction() { for (var i in nodes) { if (multiDesktop[nodes[i]._id] == null) { toggleKvmDevice(nodes[i]._id); } } }
|
function connectAllKvmFunction() { for (var i in nodes) { if (multiDesktop[nodes[i]._id] == null) { toggleKvmDevice(nodes[i]._id); } } }
|
||||||
function disconnectAllKvmFunction() { for (var nodeid in multiDesktop) { multiDesktop[nodeid].Stop(); } multiDesktop = {}; }
|
function disconnectAllKvmFunction() { for (var nodeid in multiDesktop) { multiDesktop[nodeid].Stop(); } multiDesktop = {}; }
|
||||||
@ -2728,9 +2757,30 @@
|
|||||||
|
|
||||||
function onSearchInputChanged() {
|
function onSearchInputChanged() {
|
||||||
var x = Q('SearchInput').value.toLowerCase().trim(); putstore("search", x);
|
var x = Q('SearchInput').value.toLowerCase().trim(); putstore("search", x);
|
||||||
|
var userSearch = null, ipSearch = null, groupSearch = null;
|
||||||
|
if (x.startsWith('user:')) { userSearch = x.substring(5); }
|
||||||
|
else if (x.startsWith('u:')) { userSearch = x.substring(2); }
|
||||||
|
else if (x.startsWith('ip:')) { ipSearch = x.substring(3); }
|
||||||
|
else if (x.startsWith('group:')) { groupSearch = x.substring(6); }
|
||||||
|
else if (x.startsWith('g:')) { groupSearch = x.substring(2); }
|
||||||
|
|
||||||
if (x == '') {
|
if (x == '') {
|
||||||
|
// No search
|
||||||
for (var d in nodes) { nodes[d].v = true; }
|
for (var d in nodes) { nodes[d].v = true; }
|
||||||
|
} else if (ipSearch != null) {
|
||||||
|
// IP address search
|
||||||
|
for (var d in nodes) { nodes[d].v = ((nodes[d].ip != null) && (nodes[d].ip.indexOf(ipSearch) >= 0)); }
|
||||||
|
} else if (groupSearch != null) {
|
||||||
|
// Group filter
|
||||||
|
for (var d in nodes) { nodes[d].v = (meshes[nodes[d].meshid].name.toLowerCase().indexOf(groupSearch) >= 0); }
|
||||||
|
} else if (userSearch != null) {
|
||||||
|
// User search
|
||||||
|
for (var d in nodes) {
|
||||||
|
nodes[d].v = false;
|
||||||
|
if (nodes[d].users && nodes[d].users.length > 0) { for (var i in nodes[d].users) { if (nodes[d].users[i].toLowerCase().indexOf(userSearch) >= 0) { nodes[d].v = true; } } }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Device name search
|
||||||
try {
|
try {
|
||||||
var rs = x.split(/\s+/).join('|'), rx = new RegExp(rs); // In some cases (like +), this can throw an exception.
|
var rs = x.split(/\s+/).join('|'), rx = new RegExp(rs); // In some cases (like +), this can throw an exception.
|
||||||
for (var d in nodes) {
|
for (var d in nodes) {
|
||||||
@ -4124,8 +4174,8 @@
|
|||||||
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
|
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
|
||||||
QV('DeskCAD', inputAllowed);
|
QV('DeskCAD', inputAllowed);
|
||||||
QE('DeskCAD', deskState == 3);
|
QE('DeskCAD', deskState == 3);
|
||||||
//QV('DeskClip', (desktop != null) && (desktop.contype == 1));
|
//QV('DeskClip', (desktop == null) || (desktop.contype != 2));
|
||||||
QE('DeskClip', deskState == 3);
|
//QE('DeskClip', deskState == 3);
|
||||||
QV('DeskWD', (currentNode.agent) && (currentNode.agent.id < 5) && inputAllowed);
|
QV('DeskWD', (currentNode.agent) && (currentNode.agent.id < 5) && inputAllowed);
|
||||||
QE('DeskWD', deskState == 3);
|
QE('DeskWD', deskState == 3);
|
||||||
QV('deskkeys', (currentNode.agent) && (currentNode.agent.id < 5) && inputAllowed);
|
QV('deskkeys', (currentNode.agent) && (currentNode.agent.id < 5) && inputAllowed);
|
||||||
@ -6404,17 +6454,24 @@
|
|||||||
|
|
||||||
// Get search
|
// Get search
|
||||||
var userSearch = Q('UserSearchInput').value.toLowerCase();
|
var userSearch = Q('UserSearchInput').value.toLowerCase();
|
||||||
|
var emailSearch = userSearch;
|
||||||
|
if (userSearch.startsWith('email:')) { userSearch = null; emailSearch = emailSearch.substring(6); }
|
||||||
|
else if (userSearch.startsWith('name:')) { emailSearch = null; userSearch = userSearch.substring(5); }
|
||||||
|
else if (userSearch.startsWith('e:')) { userSearch = null; emailSearch = emailSearch.substring(2); }
|
||||||
|
else if (userSearch.startsWith('n:')) { emailSearch = null; userSearch = userSearch.substring(2); }
|
||||||
|
|
||||||
// Display the users using the sorted list
|
// Display the users using the sorted list
|
||||||
var x = '<table style=width:100% cellpadding=0 cellspacing=0>', addHeader = true;
|
var x = '<table style=width:100% cellpadding=0 cellspacing=0>', addHeader = true;
|
||||||
|
|
||||||
x += '<th style=color:gray>Name<th style=color:gray;width:80px>Groups<th style=color:gray;width:120px>Last Access<th style=color:gray;width:120px>Permissions';
|
x += '<th style=color:gray>Name<th style=color:gray;width:80px>Groups<th style=color:gray;width:120px>Last Access<th style=color:gray;width:120px>Permissions';
|
||||||
|
|
||||||
// Online users
|
// Online users
|
||||||
for (var i in sortedUserIds) {
|
for (var i in sortedUserIds) {
|
||||||
var user = users[sortedUserIds[i]], sessions = null;
|
var user = users[sortedUserIds[i]], sessions = null;
|
||||||
if (wssessions != null) { sessions = wssessions[user._id]; }
|
if (wssessions != null) { sessions = wssessions[user._id]; }
|
||||||
if ((sessions != null) && (user.name.toLowerCase().indexOf(userSearch) >= 0)) {
|
if ((sessions != null) &&
|
||||||
|
((userSearch != null) && ((userSearch == '') || (user.name.toLowerCase().indexOf(userSearch) >= 0)) ||
|
||||||
|
((emailSearch != null) && ((user.email != null) && (user.email.toLowerCase().indexOf(emailSearch) >= 0))))
|
||||||
|
) {
|
||||||
if (maxUsers > 0) {
|
if (maxUsers > 0) {
|
||||||
if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>Online Users'; addHeader = false; }
|
if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>Online Users'; addHeader = false; }
|
||||||
x += addUserHtml(user, sessions);
|
x += addUserHtml(user, sessions);
|
||||||
@ -6429,7 +6486,10 @@
|
|||||||
for (var i in sortedUserIds) {
|
for (var i in sortedUserIds) {
|
||||||
var user = users[sortedUserIds[i]], sessions = null;
|
var user = users[sortedUserIds[i]], sessions = null;
|
||||||
if (wssessions != null) { sessions = wssessions[user._id]; }
|
if (wssessions != null) { sessions = wssessions[user._id]; }
|
||||||
if ((sessions == null) && (user.name.toLowerCase().indexOf(userSearch) >= 0)) {
|
if ((sessions == null) &&
|
||||||
|
((userSearch != null) && ((userSearch == '') || (user.name.toLowerCase().indexOf(userSearch) >= 0)) ||
|
||||||
|
((emailSearch != null) && ((user.email != null) && (user.email.toLowerCase().indexOf(emailSearch) >= 0))))
|
||||||
|
) {
|
||||||
if (maxUsers > 0) {
|
if (maxUsers > 0) {
|
||||||
if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>Offline Users'; addHeader = false; }
|
if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>Offline Users'; addHeader = false; }
|
||||||
x += addUserHtml(user, sessions);
|
x += addUserHtml(user, sessions);
|
||||||
|
Loading…
Reference in New Issue
Block a user