Slim down meshcore, removed WSMAN from agent.
This commit is contained in:
parent
c2bf9e62db
commit
6103589881
Binary file not shown.
Binary file not shown.
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
Loading…
Reference in New Issue