Slim down meshcore, removed WSMAN from agent.

This commit is contained in:
Ylian Saint-Hilaire 2020-10-27 23:55:00 -07:00
parent c2bf9e62db
commit 6103589881
13 changed files with 511 additions and 3341 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1161,7 +1161,7 @@ function configureAmt2() {
console.log("Unable to get Intel AMT UUID: " + apfarg.clientuuid);
exit(1); return;
} else {
settings.apftunnel = require('apfclient')({ debug: (settings.debuglevel > 0) }, apfarg);
settings.apftunnel = require('amt-apfclient')({ debug: (settings.debuglevel > 0) }, apfarg);
settings.apftunnel.onJsonControl = configureJsonControl;
settings.apftunnel.onChannelClosed = function () { exit(0); }
try {

View File

@ -213,7 +213,7 @@ function createMeshCore(agent) {
if (amt == null) return;
var func = function amtStateFunc(state) { if (state != null) { amtStateFunc.pipe._send({ cmd: 'amtstate', value: state }); } }
func.pipe = this;
amt.getAmtInfo(func);
amt.getMeiState(11, func);
break;
case 'sessions':
this._send({ cmd: 'sessions', sessions: tunnelUserCount });
@ -408,7 +408,6 @@ function createMeshCore(agent) {
var wifiScannerLib = null;
var wifiScanner = null;
var networkMonitor = null;
var amtscanner = null;
var nextTunnelIndex = 1;
var apftunnel = null;
var tunnelUserCount = { terminal: {}, files: {}, tcp: {}, udp: {}, msg: {} }; // List of userid->count sessions for terminal, files and TCP/UDP routing
@ -471,22 +470,6 @@ function createMeshCore(agent) {
mesh.DAIPC = obj.DAIPC;
/*
var AMTScanner = require("AMTScanner");
var scan = new AMTScanner();
scan.on("found", function (data) {
if (typeof data === 'string') {
console.log(data);
} else {
console.log(JSON.stringify(data, null, " "));
}
});
scan.scan("10.2.55.140", 1000);
scan.scan("10.2.55.139-10.2.55.145", 1000);
scan.scan("10.2.55.128/25", 2000);
*/
/*
// Try to load up the network monitor
try {
@ -497,13 +480,6 @@ function createMeshCore(agent) {
} catch (e) { networkMonitor = null; }
*/
// Try to load up the Intel AMT scanner
try {
var AMTScannerModule = require('amt-scanner');
amtscanner = new AMTScannerModule();
//amtscanner.on('found', function (data) { if (typeof data != 'string') { data = JSON.stringify(data, null, " "); } sendConsoleText(data); });
} catch (e) { amtscanner = null; }
// Fetch the SMBios Tables
var SMBiosTables = null;
var SMBiosTablesRaw = null;
@ -547,7 +523,7 @@ function createMeshCore(agent) {
mesh.SendCommand(meshCoreObj);
});
amt.onStateChange = function (state) { if (state == 2) { sendPeriodicServerUpdate(1); } }
amt.start();
amt.reset();
}
}
});
@ -1086,7 +1062,7 @@ function createMeshCore(agent) {
case 'amtconfig': {
// Perform Intel AMT activation and/or configuration
if ((apftunnel != null) || (amt == null) || (typeof data.user != 'string') || (typeof data.pass != 'string')) break;
getMeiState(15, function (state) {
amt.getMeiState(15, function (state) {
if ((apftunnel != null) || (amt == null)) return;
if ((state == null) || (state.ProvisioningState == null)) return;
if ((state.UUID == null) || (state.UUID.length != 36)) return; // Bad UUID
@ -1102,10 +1078,10 @@ function createMeshCore(agent) {
meiState: state // MEI state will be passed to MPS server
};
addAmtEvent('LMS tunnel start.');
apftunnel = require('apfclient')({ debug: false }, apfarg);
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
apftunnel.onJsonControl = function (data) {
if (data.action == 'console') { addAmtEvent(data.msg); } // Add console message to AMT event log
if (data.action == 'mestate') { getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
if (data.action == 'mestate') { amt.getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
if (data.action == 'deactivate') { // Request CCM deactivation
var amtMeiModule, amtMei;
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { if (apftunnel) apftunnel.sendMeiDeactivationState(1); return; }
@ -2614,8 +2590,9 @@ function createMeshCore(agent) {
var response = null;
switch (cmd) {
case 'help': { // Displays available commands
var fin = '', f = '', availcommands = 'amtconfig,amtevents,coredump,service,fdsnapshot,fdcount,startupoptions,alert,agentsize,versions,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper,agentmsg';
var fin = '', f = '', availcommands = 'coredump,service,fdsnapshot,fdcount,startupoptions,alert,agentsize,versions,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,wallpaper,agentmsg';
if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration,uac'; }
if (amt != null) { availcommands += ',amt,amtconfig,amtevents'; }
if (process.platform != 'freebsd') { availcommands += ',vm';}
if (require('MeshAgent').maxKvmTileSize != null) { availcommands += ',kvmmode'; }
try { require('zip-reader'); availcommands += ',zip,unzip'; } catch (e) { }
@ -3431,13 +3408,13 @@ function createMeshCore(agent) {
}
case 'amt': { // Show Intel AMT status
if (amt != null) {
amt.getAmtInfo(function (state) {
var resp = 'Intel AMT not detected.';
amt.getMeiState(9, function (state) {
var resp = "Intel AMT not detected.";
if (state != null) { resp = objToString(state, 0, ' ', true); }
sendConsoleText(resp, sessionid);
});
} else {
response = 'Intel AMT not detected.';
response = "Intel AMT not detected.";
}
break;
}
@ -3489,32 +3466,6 @@ function createMeshCore(agent) {
} else { response = "Wifi module not present."; }
break;
}
case 'scanamt': {
if (amtscanner != null) {
if (args['_'].length != 1) {
response = 'Usage examples:\r\n scanamt 1.2.3.4\r\n scanamt 1.2.3.0-1.2.3.255\r\n scanamt 1.2.3.0/24\r\n'; // Display correct command usage
} else {
response = 'Scanning: ' + args['_'][0] + '...';
amtscanner.scan(args['_'][0], 2000, function (data) {
if (data.length > 0) {
var r = '', pstates = ['NotActivated', 'InActivation', 'Activated'];
for (var i in data) {
var x = data[i];
if (r != '') { r += '\r\n'; }
r += x.address + ' - Intel AMT v' + x.majorVersion + '.' + x.minorVersion;
if (x.provisioningState < 3) { r += (', ' + pstates[x.provisioningState]); }
if (x.provisioningState == 2) { r += (', ' + x.openPorts.join(', ')); }
r += '.';
}
} else {
r = 'No Intel AMT found.';
}
sendConsoleText(r);
});
}
} else { response = "Intel AMT scanner module not present."; }
break;
}
case 'modules': {
response = JSON.stringify(addedModules);
break;
@ -3570,9 +3521,9 @@ function createMeshCore(agent) {
break;
}
case 'amtconfig': {
if (amt == null) { response = "Intel AMT not detected."; break; }
if (apftunnel != null) { response = "Intel AMT server tunnel already active"; break; }
if (amt == null) { response = "No Intel AMT support delected"; break; }
getMeiState(15, function (state) {
amt.getMeiState(15, function (state) {
var rx = '';
if ((state == null) || (state.ProvisioningState == null)) { rx = "Intel AMT not ready for configuration."; } else {
var apfarg = {
@ -3590,10 +3541,10 @@ function createMeshCore(agent) {
rx = "Unable to get Intel AMT UUID";
} else {
addAmtEvent('User LMS tunnel start.');
apftunnel = require('apfclient')({ debug: false }, apfarg);
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
apftunnel.onJsonControl = function (data) {
if (data.action == 'console') { addAmtEvent(data.msg); require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); } // Display a console message
if (data.action == 'mestate') { getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
if (data.action == 'mestate') { amt.getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
if (data.action == 'deactivate') { // Request CCM deactivation
var amtMeiModule, amtMei;
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { apftunnel.sendMeiDeactivationState(1); return; }
@ -3637,7 +3588,7 @@ function createMeshCore(agent) {
if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
response = "Unable to get Intel AMT UUID: " + apfarg.clientuuid;
} else {
apftunnel = require('apfclient')({ debug: false }, apfarg);
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
apftunnel.onJsonControl = function (data) {
if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); }
if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; }
@ -3761,7 +3712,7 @@ function createMeshCore(agent) {
if ((flags & 1) && (amt != null)) {
// If we have a connected MEI, get Intel ME information
amt.getAmtInfo(function (meinfo) {
amt.getMeiState(11, function (meinfo) {
try {
if (meinfo == null) return;
var intelamt = {};
@ -3871,44 +3822,6 @@ function createMeshCore(agent) {
s.data = onWebSocketData;
}
// Get Intel MEI State in a flexible way
// Flags: 1 = Versions, 2 = OsAdmin, 4 = Hashes, 8 = Network
function getMeiState(flags, func) {
var amtMeiModule, amtMei;
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { func(null); return; }
amtMei.on('error', function (e) { func(null); return; });
try {
var amtMeiTmpState = { OsHostname: require('os').hostname(), Flags: 0 }; // Flags: 1=EHBC, 2=CCM, 4=ACM
amtMei.getProtocolVersion(function (result) { if (result != null) { amtMeiTmpState.MeiVersion = result; } });
if ((flags & 1) != 0) { 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; } }); // 0: "Not Activated (Pre)", 1: "Not Activated (In)", 2: "Activated"
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; } });
if ((flags & 8) != 0) {
amtMei.getLanInterfaceSettings(0, function (result) {
if (result) {
amtMeiTmpState.net0 = result;
var fqdn = null, interfaces = require('os').networkInterfaces(); // Look for the DNS suffix for the Intel AMT Ethernet interface
for (var i in interfaces) { for (var j in interfaces[i]) { if ((interfaces[i][j].mac == result.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { amtMeiTmpState.OsDnsSuffix = interfaces[i][j].fqdn; } } }
}
});
amtMei.getLanInterfaceSettings(1, function (result) { if (result) { amtMeiTmpState.net1 = result; } });
}
amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { amtMeiTmpState.UUID = result.uuid; } });
if ((flags & 2) != 0) { amtMei.getLocalSystemAccount(function (x) { if ((x != null) && x.user && x.pass) { amtMeiTmpState.OsAdmin = { user: x.user, pass: x.pass }; } }); }
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.DnsSuffix = result; } if ((flags & 4) == 0) { if (func != null) { func(amtMeiTmpState); } } });
if ((flags & 4) != 0) {
amtMei.getHashHandles(function (handles) {
if ((handles != null) && (handles.length > 0)) { amtMeiTmpState.Hashes = []; } else { func(amtMeiTmpState); }
var exitOnCount = handles.length;
for (var i = 0; i < handles.length; ++i) { this.getCertHashEntry(handles[i], function (hashresult) { amtMeiTmpState.Hashes.push(hashresult); if (--exitOnCount == 0) { if (func != null) { func(amtMeiTmpState); } } }); }
});
}
} catch (e) { if (func != null) { func(null); } return; }
}
return obj;
}

View File

@ -1,457 +1,457 @@
/*
Copyright 2018-2020 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 APF/CIRA Client for Duktape
* @author Joko Sastriawan & Ylian Saint-Hilaire
* @copyright Intel Corporation 2020
* @license Apache-2.0
* @version v0.0.2
*/
function CreateAPFClient(parent, args) {
if ((args.clientuuid == null) || (args.clientuuid.length != 36)) return null; // Require a UUID if this exact length
var obj = {};
obj.parent = parent;
obj.args = args;
obj.http = require('http');
obj.net = require('net');
obj.forwardClient = null;
obj.downlinks = {};
obj.pfwd_idx = 0;
obj.timer = null; // Keep alive timer
// obj.onChannelClosed
// obj.onJsonControl
// Function copied from common.js
function ReadInt(v, p) { return (v.charCodeAt(p) * 0x1000000) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3); }; // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); };
function hex2rstr(d) { var r = '', m = ('' + d).match(/../g), t; while (t = m.shift()) { r += String.fromCharCode('0x' + t); } return r; };
function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }; // Convert decimal to hex
function rstr2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); } return r; }; // Convert a raw string to a hex string
function d2h(d) { return (d / 256 + 1 / 512).toString(16).substring(2, 4); }
function buf2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += d2h(input[i]); } return r; };
function Debug(str) { if (obj.parent.debug) { console.log(str); } }
function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
function strToGuid(s) { s = s.replace(/-/g, ''); var ret = s.substring(6, 8) + s.substring(4, 6) + s.substring(2, 4) + s.substring(0, 2) + s.substring(10, 12) + s.substring(8, 10) + s.substring(14, 16) + s.substring(12, 14) + s.substring(16, 20) + s.substring(20); return ret; }
function binzerostring(len) { var res = ''; for (var l = 0; l < len; l++) { res += String.fromCharCode(0 & 0xFF); } return res; }
// CIRA state
var CIRASTATE = {
INITIAL: 0,
PROTOCOL_VERSION_SENT: 1,
AUTH_SERVICE_REQUEST_SENT: 2,
AUTH_REQUEST_SENT: 3,
PFWD_SERVICE_REQUEST_SENT: 4,
GLOBAL_REQUEST_SENT: 5,
FAILED: -1
}
obj.cirastate = CIRASTATE.INITIAL;
// REDIR state
var REDIR_TYPE = {
REDIR_UNKNOWN: 0,
REDIR_SOL: 1,
REDIR_KVM: 2,
REDIR_IDER: 3
}
// redirection start command
obj.RedirectStartSol = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20);
obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
// Intel AMT forwarded port list for non-TLS mode
//var pfwd_ports = [16992, 623, 16994, 5900];
var pfwd_ports = [ 16992, 16993 ];
// protocol definitions
var APFProtocol = {
UNKNOWN: 0,
DISCONNECT: 1,
SERVICE_REQUEST: 5,
SERVICE_ACCEPT: 6,
USERAUTH_REQUEST: 50,
USERAUTH_FAILURE: 51,
USERAUTH_SUCCESS: 52,
GLOBAL_REQUEST: 80,
REQUEST_SUCCESS: 81,
REQUEST_FAILURE: 82,
CHANNEL_OPEN: 90,
CHANNEL_OPEN_CONFIRMATION: 91,
CHANNEL_OPEN_FAILURE: 92,
CHANNEL_WINDOW_ADJUST: 93,
CHANNEL_DATA: 94,
CHANNEL_CLOSE: 97,
PROTOCOLVERSION: 192,
KEEPALIVE_REQUEST: 208,
KEEPALIVE_REPLY: 209,
KEEPALIVE_OPTIONS_REQUEST: 210,
KEEPALIVE_OPTIONS_REPLY: 211,
JSON_CONTROL: 250 // This is a Mesh specific command that sends JSON to and from the MPS server.
}
var APFDisconnectCode = {
HOST_NOT_ALLOWED_TO_CONNECT: 1,
PROTOCOL_ERROR: 2,
KEY_EXCHANGE_FAILED: 3,
RESERVED: 4,
MAC_ERROR: 5,
COMPRESSION_ERROR: 6,
SERVICE_NOT_AVAILABLE: 7,
PROTOCOL_VERSION_NOT_SUPPORTED: 8,
HOST_KEY_NOT_VERIFIABLE: 9,
CONNECTION_LOST: 10,
BY_APPLICATION: 11,
TOO_MANY_CONNECTIONS: 12,
AUTH_CANCELLED_BY_USER: 13,
NO_MORE_AUTH_METHODS_AVAILABLE: 14,
INVALID_CREDENTIALS: 15,
CONNECTION_TIMED_OUT: 16,
BY_POLICY: 17,
TEMPORARILY_UNAVAILABLE: 18
}
var APFChannelOpenFailCodes = {
ADMINISTRATIVELY_PROHIBITED: 1,
CONNECT_FAILED: 2,
UNKNOWN_CHANNEL_TYPE: 3,
RESOURCE_SHORTAGE: 4,
}
var APFChannelOpenFailureReasonCode = {
AdministrativelyProhibited: 1,
ConnectFailed: 2,
UnknownChannelType: 3,
ResourceShortage: 4,
}
obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
Debug("APF Secure WebSocket connected.");
//console.log(JSON.stringify(resp));
obj.forwardClient.tag = { accumulator: [] };
obj.forwardClient.ws = ws;
obj.forwardClient.ws.on('end', function () {
Debug("APF: Connection is closing.");
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
if (obj.onChannelClosed) { obj.onChannelClosed(obj); }
});
obj.forwardClient.ws.on('data', function (data) {
obj.forwardClient.tag.accumulator += hex2rstr(buf2hex(data));
try {
var len = 0;
do {
len = ProcessData(obj.forwardClient);
if (len > 0) { obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len); }
if (obj.cirastate == CIRASTATE.FAILED) {
Debug("APF: in a failed state, destroying socket.");
obj.forwardClient.ws.end();
}
} while (len > 0);
} catch (ex) { Debug(ex); }
});
obj.forwardClient.ws.on('error', function (e) {
Debug("APF: Connection error, ending connecting.");
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
});
obj.state = CIRASTATE.INITIAL;
if ((typeof obj.args.conntype == 'number') && (obj.args.conntype != 0)) {
SendJsonControl(obj.forwardClient.ws, { action: 'connType', value: obj.args.conntype });
if (obj.args.meiState != null) { SendJsonControl(obj.forwardClient.ws, { action: 'meiState', value: obj.args.meiState }); }
}
SendProtocolVersion(obj.forwardClient.ws, obj.args.clientuuid);
SendServiceRequest(obj.forwardClient.ws, 'auth@amt.intel.com');
}
obj.updateMeiState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'meiState', value: state }); }
obj.sendMeiDeactivationState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'deactivate', value: state }); }
function SendJsonControl(socket, o) {
var data = JSON.stringify(o)
socket.write(String.fromCharCode(APFProtocol.JSON_CONTROL) + IntToStr(data.length) + data);
Debug("APF: Send JSON control: " + data);
}
function SendProtocolVersion(socket, uuid) {
var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(strToGuid(uuid)) + binzerostring(64);
socket.write(data);
Debug("APF: Send protocol version 1 0 " + uuid);
obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
}
function SendServiceRequest(socket, service) {
var data = String.fromCharCode(APFProtocol.SERVICE_REQUEST) + IntToStr(service.length) + service;
socket.write(data);
Debug("APF: Send service request " + service);
if (service == 'auth@amt.intel.com') {
obj.cirastate = CIRASTATE.AUTH_SERVICE_REQUEST_SENT;
} else if (service == 'pfwd@amt.intel.com') {
obj.cirastate = CIRASTATE.PFWD_SERVICE_REQUEST_SENT;
}
}
function SendUserAuthRequest(socket, user, pass) {
var service = "pfwd@amt.intel.com";
var data = String.fromCharCode(APFProtocol.USERAUTH_REQUEST) + IntToStr(user.length) + user + IntToStr(service.length) + service;
//password auth
data += IntToStr(8) + 'password';
data += binzerostring(1) + IntToStr(pass.length) + pass;
socket.write(data);
Debug("APF: Send username password authentication to MPS");
obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
}
function SendGlobalRequestPfwd(socket, amthostname, amtport) {
var tcpipfwd = 'tcpip-forward';
var data = String.fromCharCode(APFProtocol.GLOBAL_REQUEST) + IntToStr(tcpipfwd.length) + tcpipfwd + binzerostring(1, 1);
data += IntToStr(amthostname.length) + amthostname + IntToStr(amtport);
socket.write(data);
Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
obj.cirastate = CIRASTATE.GLOBAL_REQUEST_SENT;
}
function SendKeepAliveRequest(socket) {
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255));
Debug("APF: Send keepalive request");
}
function SendKeepAliveReply(socket, cookie) {
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie));
Debug("APF: Send keepalive reply");
}
function ProcessData(socket) {
var cmd = socket.tag.accumulator.charCodeAt(0);
var len = socket.tag.accumulator.length;
var data = socket.tag.accumulator;
if (len == 0) { return 0; }
// Respond to MPS according to obj.cirastate
switch (cmd) {
case APFProtocol.SERVICE_ACCEPT: {
var slen = ReadInt(data, 1), service = data.substring(5, 6 + slen);
Debug("APF: Service request to " + service + " accepted.");
if (service == 'auth@amt.intel.com') {
if (obj.cirastate >= CIRASTATE.AUTH_SERVICE_REQUEST_SENT) {
SendUserAuthRequest(socket.ws, obj.args.mpsuser, obj.args.mpspass);
}
} else if (service == 'pfwd@amt.intel.com') {
if (obj.cirastate >= CIRASTATE.PFWD_SERVICE_REQUEST_SENT) {
SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
}
}
return 5 + slen;
}
case APFProtocol.REQUEST_SUCCESS: {
if (len >= 5) {
var port = ReadInt(data, 1);
Debug("APF: Request to port forward " + port + " successful.");
// iterate to pending port forward request
if (obj.pfwd_idx < pfwd_ports.length) {
SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
} else {
// no more port forward, now setup timer to send keep alive
Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
obj.timer = setInterval(function () {
SendKeepAliveRequest(obj.forwardClient.ws);
}, obj.args.mpskeepalive);//
}
return 5;
}
Debug("APF: Request successful.");
return 1;
}
case APFProtocol.USERAUTH_SUCCESS: {
Debug("APF: User Authentication successful");
// Send Pfwd service request
SendServiceRequest(socket.ws, 'pfwd@amt.intel.com');
return 1;
}
case APFProtocol.USERAUTH_FAILURE: {
Debug("APF: User Authentication failed");
obj.cirastate = CIRASTATE.FAILED;
return 14;
}
case APFProtocol.KEEPALIVE_REQUEST: {
Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
SendKeepAliveReply(socket.ws, ReadInt(data, 1));
return 5;
}
case APFProtocol.KEEPALIVE_REPLY: {
Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
return 5;
}
// Channel management
case APFProtocol.CHANNEL_OPEN: {
// Parse CHANNEL OPEN request
var p_res = parseChannelOpen(data);
Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
// Check if target port is in pfwd_ports
if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
// Connect socket to that port
var chan = obj.net.createConnection({ host: obj.args.clientaddress, port: p_res.target_port }, function () {
//require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "CHANNEL_OPEN-open" });
// obj.downlinks[p_res.sender_chan].setEncoding('binary');//assume everything is binary, not interpreting
SendChannelOpenConfirm(socket.ws, p_res);
});
// Setup flow control
chan.maxInWindow = p_res.window_size; // Oddly, we are using the same window size as the other side.
chan.curInWindow = 0;
chan.on('data', function (ddata) {
// Relay data to fordwardclient
// TODO: Implement flow control
SendChannelData(socket.ws, p_res.sender_chan, ddata);
});
chan.on('error', function (e) {
//Debug("Downlink connection error: " + e);
SendChannelOpenFailure(socket.ws, p_res);
});
chan.on('end', function () {
var chan = obj.downlinks[p_res.sender_chan];
if (chan != null) {
Debug("Socket ends.");
try { SendChannelClose(socket.ws, p_res.sender_chan); } catch (ex) { }
delete obj.downlinks[p_res.sender_chan];
}
});
obj.downlinks[p_res.sender_chan] = chan;
} else {
// Not a supported port, fail the connection
SendChannelOpenFailure(socket.ws, p_res);
}
return p_res.len;
}
case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
Debug("APF: CHANNEL_OPEN_CONFIRMATION");
return 17;
}
case APFProtocol.CHANNEL_CLOSE: {
var rcpt_chan = ReadInt(data, 1);
Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
try { obj.downlinks[rcpt_chan].end(); } catch (ex) { }
return 5;
}
case APFProtocol.CHANNEL_DATA: {
Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
var rcpt_chan = ReadInt(data, 1);
var chan_data_len = ReadInt(data, 5);
var chan_data = data.substring(9, 9 + chan_data_len);
var chan = obj.downlinks[rcpt_chan];
if (chan != null) {
chan.curInWindow += chan_data_len;
try {
chan.write(Buffer.from(chan_data, 'binary'), function () {
Debug("Write completed.");
// If the incoming window is over half used, send an adjust.
if (this.curInWindow > (this.maxInWindow / 2)) { SendChannelWindowAdjust(socket.ws, rcpt_chan, this.curInWindow); this.curInWindow = 0; }
});
} catch (ex) { Debug("Cannot forward data to downlink socket."); }
}
return 9 + chan_data_len;
}
case APFProtocol.CHANNEL_WINDOW_ADJUST: {
Debug("APF: CHANNEL_WINDOW_ADJUST");
return 9;
}
case APFProtocol.JSON_CONTROL: {
Debug("APF: JSON_CONTROL");
var len = ReadInt(data, 1);
if (obj.onJsonControl) { var o = null; try { o = JSON.parse(data.substring(5, 5 + len)); } catch (ex) { } if (o != null) { obj.onJsonControl(o); } }
return 5 + len;
}
default: {
Debug("CMD: " + cmd + " is not implemented.");
obj.cirastate = CIRASTATE.FAILED;
return 0;
}
}
}
function parseChannelOpen(data) {
var result = { cmd: APFProtocol.CHANNEL_OPEN };
var chan_type_slen = ReadInt(data, 1);
result.chan_type = data.substring(5, 5 + chan_type_slen);
result.sender_chan = ReadInt(data, 5 + chan_type_slen);
result.window_size = ReadInt(data, 9 + chan_type_slen);
var c_len = ReadInt(data, 17 + chan_type_slen);
result.target_address = data.substring(21 + chan_type_slen, 21 + chan_type_slen + c_len);
result.target_port = ReadInt(data, 21 + chan_type_slen + c_len);
var o_len = ReadInt(data, 25 + chan_type_slen + c_len);
result.origin_address = data.substring(29 + chan_type_slen + c_len, 29 + chan_type_slen + c_len + o_len);
result.origin_port = ReadInt(data, 29 + chan_type_slen + c_len + o_len);
result.len = 33 + chan_type_slen + c_len + o_len;
return result;
}
function SendChannelOpenFailure(socket, chan_data) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan) + IntToStr(2) + IntToStr(0) + IntToStr(0));
Debug("APF: Send ChannelOpenFailure");
}
function SendChannelOpenConfirm(socket, chan_data) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.window_size) + IntToStr(0xFFFFFFFF));
Debug("APF: Send ChannelOpenConfirmation");
}
function SendChannelWindowAdjust(socket, chan, size) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size));
Debug("APF: Send ChannelWindowAdjust, channel: " + chan + ", size: " + size);
}
function SendChannelData(socket, chan, data) {
socket.write(Buffer.concat([Buffer.from(String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(data.length), 'binary'), data]));
Debug("APF: Send ChannelData: " + data.toString('hex'));
}
function SendChannelClose(socket, chan) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan));
Debug("APF: Send ChannelClose ");
}
obj.connect = function () {
if (obj.forwardClient != null) {
try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); }
//obj.forwardClient = null;
}
obj.cirastate = CIRASTATE.INITIAL;
obj.pfwd_idx = 0;
//obj.forwardClient = new obj.ws(obj.args.mpsurl, obj.tlsoptions);
//obj.forwardClient.on("open", obj.onSecureConnect);
var wsoptions = obj.http.parseUri(obj.args.mpsurl);
wsoptions.rejectUnauthorized = 0;
obj.forwardClient = obj.http.request(wsoptions);
obj.forwardClient.upgrade = obj.onSecureConnect;
obj.forwardClient.end(); // end request, trigger completion of HTTP request
}
obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); } }
return obj;
}
/*
Copyright 2018-2020 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 APF/CIRA Client for Duktape
* @author Joko Sastriawan & Ylian Saint-Hilaire
* @copyright Intel Corporation 2020
* @license Apache-2.0
* @version v0.0.2
*/
function CreateAPFClient(parent, args) {
if ((args.clientuuid == null) || (args.clientuuid.length != 36)) return null; // Require a UUID if this exact length
var obj = {};
obj.parent = parent;
obj.args = args;
obj.http = require('http');
obj.net = require('net');
obj.forwardClient = null;
obj.downlinks = {};
obj.pfwd_idx = 0;
obj.timer = null; // Keep alive timer
// obj.onChannelClosed
// obj.onJsonControl
// Function copied from common.js
function ReadInt(v, p) { return (v.charCodeAt(p) * 0x1000000) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3); }; // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); };
function hex2rstr(d) { var r = '', m = ('' + d).match(/../g), t; while (t = m.shift()) { r += String.fromCharCode('0x' + t); } return r; };
function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }; // Convert decimal to hex
function rstr2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); } return r; }; // Convert a raw string to a hex string
function d2h(d) { return (d / 256 + 1 / 512).toString(16).substring(2, 4); }
function buf2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += d2h(input[i]); } return r; };
function Debug(str) { if (obj.parent.debug) { console.log(str); } }
function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
function strToGuid(s) { s = s.replace(/-/g, ''); var ret = s.substring(6, 8) + s.substring(4, 6) + s.substring(2, 4) + s.substring(0, 2) + s.substring(10, 12) + s.substring(8, 10) + s.substring(14, 16) + s.substring(12, 14) + s.substring(16, 20) + s.substring(20); return ret; }
function binzerostring(len) { var res = ''; for (var l = 0; l < len; l++) { res += String.fromCharCode(0 & 0xFF); } return res; }
// CIRA state
var CIRASTATE = {
INITIAL: 0,
PROTOCOL_VERSION_SENT: 1,
AUTH_SERVICE_REQUEST_SENT: 2,
AUTH_REQUEST_SENT: 3,
PFWD_SERVICE_REQUEST_SENT: 4,
GLOBAL_REQUEST_SENT: 5,
FAILED: -1
}
obj.cirastate = CIRASTATE.INITIAL;
// REDIR state
var REDIR_TYPE = {
REDIR_UNKNOWN: 0,
REDIR_SOL: 1,
REDIR_KVM: 2,
REDIR_IDER: 3
}
// redirection start command
obj.RedirectStartSol = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20);
obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
// Intel AMT forwarded port list for non-TLS mode
//var pfwd_ports = [16992, 623, 16994, 5900];
var pfwd_ports = [ 16992, 16993 ];
// protocol definitions
var APFProtocol = {
UNKNOWN: 0,
DISCONNECT: 1,
SERVICE_REQUEST: 5,
SERVICE_ACCEPT: 6,
USERAUTH_REQUEST: 50,
USERAUTH_FAILURE: 51,
USERAUTH_SUCCESS: 52,
GLOBAL_REQUEST: 80,
REQUEST_SUCCESS: 81,
REQUEST_FAILURE: 82,
CHANNEL_OPEN: 90,
CHANNEL_OPEN_CONFIRMATION: 91,
CHANNEL_OPEN_FAILURE: 92,
CHANNEL_WINDOW_ADJUST: 93,
CHANNEL_DATA: 94,
CHANNEL_CLOSE: 97,
PROTOCOLVERSION: 192,
KEEPALIVE_REQUEST: 208,
KEEPALIVE_REPLY: 209,
KEEPALIVE_OPTIONS_REQUEST: 210,
KEEPALIVE_OPTIONS_REPLY: 211,
JSON_CONTROL: 250 // This is a Mesh specific command that sends JSON to and from the MPS server.
}
var APFDisconnectCode = {
HOST_NOT_ALLOWED_TO_CONNECT: 1,
PROTOCOL_ERROR: 2,
KEY_EXCHANGE_FAILED: 3,
RESERVED: 4,
MAC_ERROR: 5,
COMPRESSION_ERROR: 6,
SERVICE_NOT_AVAILABLE: 7,
PROTOCOL_VERSION_NOT_SUPPORTED: 8,
HOST_KEY_NOT_VERIFIABLE: 9,
CONNECTION_LOST: 10,
BY_APPLICATION: 11,
TOO_MANY_CONNECTIONS: 12,
AUTH_CANCELLED_BY_USER: 13,
NO_MORE_AUTH_METHODS_AVAILABLE: 14,
INVALID_CREDENTIALS: 15,
CONNECTION_TIMED_OUT: 16,
BY_POLICY: 17,
TEMPORARILY_UNAVAILABLE: 18
}
var APFChannelOpenFailCodes = {
ADMINISTRATIVELY_PROHIBITED: 1,
CONNECT_FAILED: 2,
UNKNOWN_CHANNEL_TYPE: 3,
RESOURCE_SHORTAGE: 4,
}
var APFChannelOpenFailureReasonCode = {
AdministrativelyProhibited: 1,
ConnectFailed: 2,
UnknownChannelType: 3,
ResourceShortage: 4,
}
obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
Debug("APF Secure WebSocket connected.");
//console.log(JSON.stringify(resp));
obj.forwardClient.tag = { accumulator: [] };
obj.forwardClient.ws = ws;
obj.forwardClient.ws.on('end', function () {
Debug("APF: Connection is closing.");
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
if (obj.onChannelClosed) { obj.onChannelClosed(obj); }
});
obj.forwardClient.ws.on('data', function (data) {
obj.forwardClient.tag.accumulator += hex2rstr(buf2hex(data));
try {
var len = 0;
do {
len = ProcessData(obj.forwardClient);
if (len > 0) { obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len); }
if (obj.cirastate == CIRASTATE.FAILED) {
Debug("APF: in a failed state, destroying socket.");
obj.forwardClient.ws.end();
}
} while (len > 0);
} catch (ex) { Debug(ex); }
});
obj.forwardClient.ws.on('error', function (e) {
Debug("APF: Connection error, ending connecting.");
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
});
obj.state = CIRASTATE.INITIAL;
if ((typeof obj.args.conntype == 'number') && (obj.args.conntype != 0)) {
SendJsonControl(obj.forwardClient.ws, { action: 'connType', value: obj.args.conntype });
if (obj.args.meiState != null) { SendJsonControl(obj.forwardClient.ws, { action: 'meiState', value: obj.args.meiState }); }
}
SendProtocolVersion(obj.forwardClient.ws, obj.args.clientuuid);
SendServiceRequest(obj.forwardClient.ws, 'auth@amt.intel.com');
}
obj.updateMeiState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'meiState', value: state }); }
obj.sendMeiDeactivationState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'deactivate', value: state }); }
function SendJsonControl(socket, o) {
var data = JSON.stringify(o)
socket.write(String.fromCharCode(APFProtocol.JSON_CONTROL) + IntToStr(data.length) + data);
Debug("APF: Send JSON control: " + data);
}
function SendProtocolVersion(socket, uuid) {
var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(strToGuid(uuid)) + binzerostring(64);
socket.write(data);
Debug("APF: Send protocol version 1 0 " + uuid);
obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
}
function SendServiceRequest(socket, service) {
var data = String.fromCharCode(APFProtocol.SERVICE_REQUEST) + IntToStr(service.length) + service;
socket.write(data);
Debug("APF: Send service request " + service);
if (service == 'auth@amt.intel.com') {
obj.cirastate = CIRASTATE.AUTH_SERVICE_REQUEST_SENT;
} else if (service == 'pfwd@amt.intel.com') {
obj.cirastate = CIRASTATE.PFWD_SERVICE_REQUEST_SENT;
}
}
function SendUserAuthRequest(socket, user, pass) {
var service = "pfwd@amt.intel.com";
var data = String.fromCharCode(APFProtocol.USERAUTH_REQUEST) + IntToStr(user.length) + user + IntToStr(service.length) + service;
//password auth
data += IntToStr(8) + 'password';
data += binzerostring(1) + IntToStr(pass.length) + pass;
socket.write(data);
Debug("APF: Send username password authentication to MPS");
obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
}
function SendGlobalRequestPfwd(socket, amthostname, amtport) {
var tcpipfwd = 'tcpip-forward';
var data = String.fromCharCode(APFProtocol.GLOBAL_REQUEST) + IntToStr(tcpipfwd.length) + tcpipfwd + binzerostring(1, 1);
data += IntToStr(amthostname.length) + amthostname + IntToStr(amtport);
socket.write(data);
Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
obj.cirastate = CIRASTATE.GLOBAL_REQUEST_SENT;
}
function SendKeepAliveRequest(socket) {
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255));
Debug("APF: Send keepalive request");
}
function SendKeepAliveReply(socket, cookie) {
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie));
Debug("APF: Send keepalive reply");
}
function ProcessData(socket) {
var cmd = socket.tag.accumulator.charCodeAt(0);
var len = socket.tag.accumulator.length;
var data = socket.tag.accumulator;
if (len == 0) { return 0; }
// Respond to MPS according to obj.cirastate
switch (cmd) {
case APFProtocol.SERVICE_ACCEPT: {
var slen = ReadInt(data, 1), service = data.substring(5, 6 + slen);
Debug("APF: Service request to " + service + " accepted.");
if (service == 'auth@amt.intel.com') {
if (obj.cirastate >= CIRASTATE.AUTH_SERVICE_REQUEST_SENT) {
SendUserAuthRequest(socket.ws, obj.args.mpsuser, obj.args.mpspass);
}
} else if (service == 'pfwd@amt.intel.com') {
if (obj.cirastate >= CIRASTATE.PFWD_SERVICE_REQUEST_SENT) {
SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
}
}
return 5 + slen;
}
case APFProtocol.REQUEST_SUCCESS: {
if (len >= 5) {
var port = ReadInt(data, 1);
Debug("APF: Request to port forward " + port + " successful.");
// iterate to pending port forward request
if (obj.pfwd_idx < pfwd_ports.length) {
SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
} else {
// no more port forward, now setup timer to send keep alive
Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
obj.timer = setInterval(function () {
SendKeepAliveRequest(obj.forwardClient.ws);
}, obj.args.mpskeepalive);//
}
return 5;
}
Debug("APF: Request successful.");
return 1;
}
case APFProtocol.USERAUTH_SUCCESS: {
Debug("APF: User Authentication successful");
// Send Pfwd service request
SendServiceRequest(socket.ws, 'pfwd@amt.intel.com');
return 1;
}
case APFProtocol.USERAUTH_FAILURE: {
Debug("APF: User Authentication failed");
obj.cirastate = CIRASTATE.FAILED;
return 14;
}
case APFProtocol.KEEPALIVE_REQUEST: {
Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
SendKeepAliveReply(socket.ws, ReadInt(data, 1));
return 5;
}
case APFProtocol.KEEPALIVE_REPLY: {
Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
return 5;
}
// Channel management
case APFProtocol.CHANNEL_OPEN: {
// Parse CHANNEL OPEN request
var p_res = parseChannelOpen(data);
Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
// Check if target port is in pfwd_ports
if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
// Connect socket to that port
var chan = obj.net.createConnection({ host: obj.args.clientaddress, port: p_res.target_port }, function () {
//require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "CHANNEL_OPEN-open" });
// obj.downlinks[p_res.sender_chan].setEncoding('binary');//assume everything is binary, not interpreting
SendChannelOpenConfirm(socket.ws, p_res);
});
// Setup flow control
chan.maxInWindow = p_res.window_size; // Oddly, we are using the same window size as the other side.
chan.curInWindow = 0;
chan.on('data', function (ddata) {
// Relay data to fordwardclient
// TODO: Implement flow control
SendChannelData(socket.ws, p_res.sender_chan, ddata);
});
chan.on('error', function (e) {
//Debug("Downlink connection error: " + e);
SendChannelOpenFailure(socket.ws, p_res);
});
chan.on('end', function () {
var chan = obj.downlinks[p_res.sender_chan];
if (chan != null) {
Debug("Socket ends.");
try { SendChannelClose(socket.ws, p_res.sender_chan); } catch (ex) { }
delete obj.downlinks[p_res.sender_chan];
}
});
obj.downlinks[p_res.sender_chan] = chan;
} else {
// Not a supported port, fail the connection
SendChannelOpenFailure(socket.ws, p_res);
}
return p_res.len;
}
case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
Debug("APF: CHANNEL_OPEN_CONFIRMATION");
return 17;
}
case APFProtocol.CHANNEL_CLOSE: {
var rcpt_chan = ReadInt(data, 1);
Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
try { obj.downlinks[rcpt_chan].end(); } catch (ex) { }
return 5;
}
case APFProtocol.CHANNEL_DATA: {
Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
var rcpt_chan = ReadInt(data, 1);
var chan_data_len = ReadInt(data, 5);
var chan_data = data.substring(9, 9 + chan_data_len);
var chan = obj.downlinks[rcpt_chan];
if (chan != null) {
chan.curInWindow += chan_data_len;
try {
chan.write(Buffer.from(chan_data, 'binary'), function () {
Debug("Write completed.");
// If the incoming window is over half used, send an adjust.
if (this.curInWindow > (this.maxInWindow / 2)) { SendChannelWindowAdjust(socket.ws, rcpt_chan, this.curInWindow); this.curInWindow = 0; }
});
} catch (ex) { Debug("Cannot forward data to downlink socket."); }
}
return 9 + chan_data_len;
}
case APFProtocol.CHANNEL_WINDOW_ADJUST: {
Debug("APF: CHANNEL_WINDOW_ADJUST");
return 9;
}
case APFProtocol.JSON_CONTROL: {
Debug("APF: JSON_CONTROL");
var len = ReadInt(data, 1);
if (obj.onJsonControl) { var o = null; try { o = JSON.parse(data.substring(5, 5 + len)); } catch (ex) { } if (o != null) { obj.onJsonControl(o); } }
return 5 + len;
}
default: {
Debug("CMD: " + cmd + " is not implemented.");
obj.cirastate = CIRASTATE.FAILED;
return 0;
}
}
}
function parseChannelOpen(data) {
var result = { cmd: APFProtocol.CHANNEL_OPEN };
var chan_type_slen = ReadInt(data, 1);
result.chan_type = data.substring(5, 5 + chan_type_slen);
result.sender_chan = ReadInt(data, 5 + chan_type_slen);
result.window_size = ReadInt(data, 9 + chan_type_slen);
var c_len = ReadInt(data, 17 + chan_type_slen);
result.target_address = data.substring(21 + chan_type_slen, 21 + chan_type_slen + c_len);
result.target_port = ReadInt(data, 21 + chan_type_slen + c_len);
var o_len = ReadInt(data, 25 + chan_type_slen + c_len);
result.origin_address = data.substring(29 + chan_type_slen + c_len, 29 + chan_type_slen + c_len + o_len);
result.origin_port = ReadInt(data, 29 + chan_type_slen + c_len + o_len);
result.len = 33 + chan_type_slen + c_len + o_len;
return result;
}
function SendChannelOpenFailure(socket, chan_data) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan) + IntToStr(2) + IntToStr(0) + IntToStr(0));
Debug("APF: Send ChannelOpenFailure");
}
function SendChannelOpenConfirm(socket, chan_data) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.window_size) + IntToStr(0xFFFFFFFF));
Debug("APF: Send ChannelOpenConfirmation");
}
function SendChannelWindowAdjust(socket, chan, size) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size));
Debug("APF: Send ChannelWindowAdjust, channel: " + chan + ", size: " + size);
}
function SendChannelData(socket, chan, data) {
socket.write(Buffer.concat([Buffer.from(String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(data.length), 'binary'), data]));
Debug("APF: Send ChannelData: " + data.toString('hex'));
}
function SendChannelClose(socket, chan) {
socket.write(String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan));
Debug("APF: Send ChannelClose ");
}
obj.connect = function () {
if (obj.forwardClient != null) {
try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); }
//obj.forwardClient = null;
}
obj.cirastate = CIRASTATE.INITIAL;
obj.pfwd_idx = 0;
//obj.forwardClient = new obj.ws(obj.args.mpsurl, obj.tlsoptions);
//obj.forwardClient.on("open", obj.onSecureConnect);
var wsoptions = obj.http.parseUri(obj.args.mpsurl);
wsoptions.rejectUnauthorized = 0;
obj.forwardClient = obj.http.request(wsoptions);
obj.forwardClient.upgrade = obj.onSecureConnect;
obj.forwardClient.end(); // end request, trigger completion of HTTP request
}
obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); } }
return obj;
}
module.exports = CreateAPFClient;

View File

@ -305,7 +305,7 @@ function lme_heci(options) {
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)); }
if (notify != null) { this.LMS.emit('notify', notify, channel.options, _lmsNotifyToCode(notify)); }
// Send channel close
var buffer = Buffer.alloc(5);
@ -458,447 +458,4 @@ function _lmsNotifyToCode(notify) {
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;

View File

@ -30,9 +30,6 @@ function AmtManager(agent, db, isdebug) {
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;
var mestate;
var trustedHashes = null;;
@ -43,41 +40,19 @@ function AmtManager(agent, db, isdebug) {
obj._lmsstate = 0;
obj._mapping = [];
obj.on('newListener', function (name, callback)
{
if(name == 'portBinding_LMS')
{
callback.call(this, this._mapping);
}
obj.on('newListener', function (name, callback) {
if (name == 'portBinding_LMS') { callback.call(this, this._mapping); }
});
Object.defineProperty(obj, 'lmsstate',
{
get: function ()
{
return (this._lmsstate);
},
set: function (value)
{
if (this._lmsstate != value)
{
this._lmsstate = value;
this.emit('stateChange_LMS', value);
}
}
get: function () { return (this._lmsstate); },
set: function (value) { if (this._lmsstate != value) { this._lmsstate = value; this.emit('stateChange_LMS', value); } }
});
obj.state = 0;
obj.onStateChange = null;
obj.setDebug = function (x) { isdebug = x; }
// Set current Intel AMT activation policy
obj.setPolicy = function (policy, forceApply) {
if (forceApply || (JSON.stringify(amtpolicy) != JSON.stringify(policy))) {
amtpolicy = policy;
if (applyPolicyTimer == null) { applyPolicyTimer = setTimeout(obj.applyPolicy, 8000); }
}
}
// Try to load up the MEI module
var rebindToMeiRetrys = 0;
@ -91,14 +66,12 @@ function AmtManager(agent, db, isdebug) {
amtMei.on('error', function (e) { debug('MEI error'); amtMei = null; amtMeiState = -1; obj.state = -1; if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); } });
amtMei.getVersion(function (result) {
if (result == null) {
amtMeiState = -1;
obj.state = -1;
obj.state = amtMeiState = -1;
if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
if (rebindToMeiRetrys < 10) { setTimeout(obj.reset, 10000); }
} else {
amtGetVersionResult = result;
amtMeiState = 2;
obj.state = 2;
obj.state = amtMeiState = 2;
rebindToMeiRetrys = 0;
if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
//debug('MEI binded');
@ -108,28 +81,44 @@ function AmtManager(agent, db, isdebug) {
} 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) {
// Get Intel MEI State in a flexible way
// Flags: 1 = Versions, 2 = OsAdmin, 4 = Hashes, 8 = Network
obj.getMeiState = function(flags, func) {
if ((amtMei == null) || (amtMeiState < 2)) { if (func != null) { func(null); } return; }
try {
amtMeiTmpState = { Flags: 0 }; // Flags: 1=EHBC, 2=CCM, 4=ACM
var amtMeiTmpState = { OsHostname: require('os').hostname(), 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; } } });
if ((flags & 1) != 0) { 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.getProvisioningState(function (result) { if (result) { amtMeiTmpState.ProvisioningState = result.state; } }); // 0: "Not Activated (Pre)", 1: "Not Activated (In)", 2: "Activated"
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; } });
if ((flags & 8) != 0) {
amtMei.getLanInterfaceSettings(0, function (result) {
if (result) {
amtMeiTmpState.net0 = result;
var fqdn = null, interfaces = require('os').networkInterfaces(); // Look for the DNS suffix for the Intel AMT Ethernet interface
for (var i in interfaces) { for (var j in interfaces[i]) { if ((interfaces[i][j].mac == result.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { amtMeiTmpState.OsDnsSuffix = interfaces[i][j].fqdn; } } }
}
});
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); } });
if ((flags & 2) != 0) { amtMei.getLocalSystemAccount(function (x) { if ((x != null) && x.user && x.pass) { amtMeiTmpState.OsAdmin = { user: x.user, pass: x.pass }; } }); }
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.DnsSuffix = result; } if ((flags & 4) == 0) { if (func != null) { func(amtMeiTmpState); } } });
if ((flags & 4) != 0) {
amtMei.getHashHandles(function (handles) {
if ((handles != null) && (handles.length > 0)) { amtMeiTmpState.Hashes = []; } else { func(amtMeiTmpState); }
var exitOnCount = handles.length;
for (var i = 0; i < handles.length; ++i) { this.getCertHashEntry(handles[i], function (hashresult) { amtMeiTmpState.Hashes.push(hashresult); if (--exitOnCount == 0) { if (func != null) { func(amtMeiTmpState); } } }); }
});
}
} catch (e) { if (func != null) { func(null); } return; }
}
// Called on MicroLMS Intel AMT user notification
var handleAmtNotification = function(notifyMsg) {
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;
@ -149,632 +138,15 @@ function AmtManager(agent, db, isdebug) {
obj.lmsstate = 0;
try {
var lme_heci = require('amt-lme');
amtLmsState = 1;
obj.lmsstate = 1;
obj.lmsstate = amtLmsState = 1;
amtLms = new lme_heci();
amtLms.on('error', function (e) { amtLmsState = 0; obj.lmsstate = 0; amtLms = null; debug("LMS error: " + e); setupMeiOsAdmin(1); });
amtLms.on('connect', function () { amtLmsState = 2; obj.lmsstate = 2; debug("LMS connected"); setupMeiOsAdmin(2); });
amtLms.on('bind', function (map)
{
obj._mapping = map;
obj.emit('portBinding_LMS', 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);
}
});
amtLms.on('error', function (e) { amtLmsState = 0; obj.lmsstate = 0; amtLms = null; debug("LMS error: " + e); });
amtLms.on('connect', function () { amtLmsState = 2; obj.lmsstate = 2; debug("LMS connected"); });
amtLms.on('bind', function (map) { obj._mapping = map; obj.emit('portBinding_LMS', map); });
amtLms.on('notify', function (data, options, code) { 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);
}
});
}
//
// Get Intel AMT activation hashes
//
obj.getTrustedHashes = function (func, tag) {
if (trustedHashes != null) { func(tag); }
trustedHashes = [];
amtMei.getHashHandles(function (handles) {
var exitOnCount = handles.length;
for (var i = 0; i < handles.length; ++i) {
this.getCertHashEntry(handles[i], function (result) {
if (result.isActive == 1) { trustedHashes.push(result.certificateHash.toLowerCase()); }
if (--exitOnCount == 0) { func(tag); }
});
}
});
}
//
// Activate Intel AMT to ACM
//
obj.activeToACM = function (mestate) {
if ((mestate.ProvisioningState != 0) || (amtpolicy == null) || (amtpolicy.match == null)) return; // Can't activate unless in "PRE" activation mode & policy is present.
var trustedFqdn = null;
if ((mestate.net0 == null) && (mestate.net0.enabled != 0)) return; // Can't activate unless wired interface is active
if (mestate.DNS) { trustedFqdn = mestate.DNS; } // If Intel AMT has a trusted DNS suffix set, use that one.
else {
// Look for the DNS suffix for the Intel AMT Ethernet interface
var interfaces = require('os').networkInterfaces();
for (var i in interfaces) {
for (var j in interfaces[i]) {
if ((interfaces[i][j].mac == mestate.net0.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { trustedFqdn = interfaces[i][j].fqdn.toLowerCase(); }
}
}
}
if (trustedFqdn == null) return; // No trusted DNS suffix.
// Check if we have a ACM policy match
var hashMatch = null;
for (var i in amtpolicy.match) { var m = amtpolicy.match[i]; if (m.cn == trustedFqdn) { for (var j in trustedHashes) { if ((trustedHashes[j] == m.sha256) || (trustedHashes[j] == m.sha1)) { hashMatch = trustedHashes[j]; } } } }
if (hashMatch == null) return; // No certificate / FQDN match
// Fetch Intel AMT realm and activation nonce and get ready to ACM activation...
if (osamtstack != null) {
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch, uuid: mestate.UUID });
} else {
amtMei.getLocalSystemAccount(function (x) {
if ((x != null) && x.user && 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);
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch, uuid: mestate.UUID });
}
});
}
}
function activeToACM2(stack, name, responses, status, tag) {
if (status != 200) return;
var fwNonce = responses['IPS_HostBasedSetupService'].response['ConfigurationNonce'];
var digestRealm = responses['AMT_GeneralSettings'].response['DigestRealm'];
agent.SendCommand({ "action": "acmactivate", "nonce": fwNonce, "realm": digestRealm, "fqdn": tag.fqdn, "hash": tag.hash, "uuid": tag.uuid });
}
// Called when the server responds with a ACM activation signature.
obj.setAcmResponse = function (acmdata) { acmdata.index = 0; performAcmActivation(acmdata); }
// Recursive function to inject the provisioning certificates into AMT in the proper order and completes ACM activation
function performAcmActivation(acmdata) {
var leaf = (acmdata.index == 0), root = (acmdata.index == (acmdata.certs.length - 1));
if ((acmdata.index < acmdata.certs.length) && (acmdata.certs[acmdata.index] != null)) {
osamtstack.IPS_HostBasedSetupService_AddNextCertInChain(acmdata.certs[acmdata.index], leaf, root, function (stack, name, responses, status) {
if (status !== 200) { debug('AddNextCertInChain status=' + status); return; }
else if (responses['Body']['ReturnValue'] !== 0) { debug('AddNextCertInChain error=' + responses['Body']['ReturnValue']); return; }
else { acmdata.index++; performAcmActivation(acmdata); }
});
} else {
osamtstack.IPS_HostBasedSetupService_AdminSetup(2, acmdata.password, acmdata.nonce, 2, acmdata.signature,
function (stack, name, responses, status) {
if ((status == 200) && (responses['Body']['ReturnValue'] == 0)) {
// ACM activation success, force an update to the server so it can get our new state.
if (obj.onStateChange != null) { obj.onStateChange(2); }
}
}
);
}
}
//
// Activate Intel AMT to CCM
//
obj.makePass = function(length) {
var buf = Buffer.alloc(length), text = "", possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
buf.randomFill(); // Fills buffer with secure random from OpenSSL.
for (var i = 0; i < length; i++) { text += possible.charAt(buf[i] % possible.length); }
return text;
}
obj.activeToCCM = function (adminpass) {
if ((adminpass == null) || (adminpass == '')) { adminpass = 'P@0s' + obj.makePass(23); }
intelAmtAdminPass = adminpass;
if (osamtstack != null) {
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToCCMEx2, adminpass);
} else {
//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) || (amtpolicy == null) || (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 = amtstack = null;
obj.deactivateCCM();
} else if ((amtpolicy.type == 2) && (meinfo.ProvisioningState == 0)) {
// CCM Activation Policy
wsstack = 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 if ((amtpolicy.type == 3) && (meinfo.ProvisioningState == 0) && (agent.isControlChannelConnected)) {
// ACM Activation Policy
obj.getTrustedHashes(obj.activeToACM, meinfo);
} 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;

View File

@ -1,109 +0,0 @@
/*
Copyright 2018-2020 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))+1, max: (ip & (0xFFFFFFFF - mask)) + mask -1 };//remove network and broadcast address to avoid irrecoverable socket error
}
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, callback) {
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();
if (callback) {
callback(server.scanResults);
}
server.parent.emit('found', server.scanResults);
delete server;
}, timeout);
};
}
module.exports = AMTScanner;

View File

@ -1,147 +0,0 @@
/*
Copyright 2018-2020 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;

View File

@ -1,211 +0,0 @@
/*
Copyright 2018-2020 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 == null) || (selectorSet == 'null')) 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;

View File

@ -1,189 +0,0 @@
/*
Copyright 2018-2020 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;
var x = t.indexOf('_OUTPUT');
if ((x != -1) && (x == (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) {
try {
if (text == null) return null;
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(); }
}
}
} catch (ex) { return null; }
return lastElement;
}

File diff suppressed because it is too large Load Diff