mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-27 15:45:53 -05:00
Added Intel AMT tunneling configuration support.
This commit is contained in:
parent
9aab9a98e3
commit
c0eab31b02
@ -113,7 +113,7 @@ function run(argv) {
|
||||
//console.log('addedModules = ' + JSON.stringify(addedModules));
|
||||
var actionpath = 'meshaction.txt';
|
||||
if (args.actionfile != null) { actionpath = args.actionfile; }
|
||||
var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTSCAN', 'AMTPOWER', 'AMTFEATURES', 'AMTNETWORK', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTINFODEBUG', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTACM', 'AMTDEACTIVATE', 'AMTACMDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTEVENTLOG', 'AMTPRESENCE', 'AMTWIFI', 'AMTWAKE'];
|
||||
var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTCONFIG', 'AMTSCAN', 'AMTPOWER', 'AMTFEATURES', 'AMTNETWORK', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTINFODEBUG', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTACM', 'AMTDEACTIVATE', 'AMTACMDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTEVENTLOG', 'AMTPRESENCE', 'AMTWIFI', 'AMTWAKE'];
|
||||
|
||||
// Load the action file
|
||||
var actionfile = null;
|
||||
@ -129,6 +129,7 @@ function run(argv) {
|
||||
if ((typeof args.localport) == 'string') { settings.localport = parseInt(args.localport); }
|
||||
if ((typeof args.remotenodeid) == 'string') { settings.remotenodeid = args.remotenodeid; }
|
||||
if ((typeof args.name) == 'string') { settings.name = args.name; }
|
||||
if ((typeof args.id) == 'string') { settings.id = args.id; }
|
||||
if ((typeof args.username) == 'string') { settings.username = args.username; }
|
||||
if ((typeof args.password) == 'string') { settings.password = args.password; }
|
||||
if ((typeof args.url) == 'string') { settings.url = args.url; }
|
||||
@ -174,6 +175,7 @@ function run(argv) {
|
||||
console.log(' meshcmd [action] [arguments...]\r\n');
|
||||
console.log('Valid MeshCentral actions:');
|
||||
console.log(' Route - Map a local TCP port to a remote computer.');
|
||||
console.log(' AmtConfig - Setup Intel AMT on this computer.');
|
||||
console.log('\r\nValid local actions:');
|
||||
console.log(' SMBios - Display System Management BIOS tables for this computer.');
|
||||
console.log(' RawSMBios - Display RAW System Management BIOS tables for this computer.');
|
||||
@ -245,6 +247,12 @@ function run(argv) {
|
||||
console.log(' --tag [string] Optional string sent to the server during activation.');
|
||||
console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.');
|
||||
console.log(' --profile [string] Optional profile used for server activation.');
|
||||
} else if (action == 'amtconfig') {
|
||||
console.log('AmtConfig will attempt to activate and configure Intel AMT on this computer. The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Example usage:\r\n\r\n meshcmd amtconfig --url [url]');
|
||||
console.log('\r\nPossible arguments:\r\n');
|
||||
console.log(' --url [wss://server] The address of the MeshCentral server.');
|
||||
console.log(' --id [groupid] The device group identifier.');
|
||||
console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.');
|
||||
} else if (action == 'amtacm') {
|
||||
console.log('AmtACM will attempt to activate Intel AMT on this computer into admin control mode (ACM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work. Example usage:\r\n\r\n meshcmd amtacm --url [url]');
|
||||
console.log('\r\nPossible arguments:\r\n');
|
||||
@ -643,6 +651,12 @@ function run(argv) {
|
||||
settings.localport = 16992;
|
||||
debug(1, "Settings: " + JSON.stringify(settings));
|
||||
getAmtUuid();
|
||||
} else if (settings.action == 'amtconfig') {
|
||||
// Start Intel AMT configuration
|
||||
if ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == '')) { console.log('No MeshCentral server URL specified, use --url [url].'); exit(1); return; }
|
||||
if ((settings.id == null) || (typeof settings.id != 'string') || (settings.id == '')) { console.log('No device group identifier specified, use --id [identifier].'); exit(1); return; }
|
||||
debug(1, "Settings: " + JSON.stringify(settings));
|
||||
configureAmt();
|
||||
} else if (settings.action == 'amtccm') {
|
||||
// Start activation to CCM
|
||||
if (((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) && ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == ''))) { console.log('No or invalid parameters specified, use --password [password] or --url [url].'); exit(1); return; }
|
||||
@ -1127,6 +1141,88 @@ function startMeshCommander() {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Configure Intel AMT
|
||||
//
|
||||
|
||||
function configureAmt() {
|
||||
console.log('Starting Intel AMT configuration...');
|
||||
settings.noconsole = true;
|
||||
|
||||
// Display Intel AMT version and activation state
|
||||
mestate = {};
|
||||
var amtMeiModule, amtMei;
|
||||
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { console.log(ex); exit(1); return; }
|
||||
amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; });
|
||||
amtMei.getProvisioningState(function (result) { if (result) { mestate.ProvisioningState = result; } });
|
||||
amtMei.getVersion(function (val) { mestate.vers = {}; if (val != null) { for (var version in val.Versions) { mestate.vers[val.Versions[version].Description] = val.Versions[version].Version; } } });
|
||||
amtMei.getLanInterfaceSettings(0, function (result) { if (result) { mestate.net0 = result; } });
|
||||
amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } });
|
||||
amtMei.getControlMode(function (result) { if (result != null) { mestate.controlMode = result.controlMode; } }); // controlMode: 0 = NoActivated, 1 = CCM, 2 = ACM
|
||||
amtMei.getDnsSuffix(function (result) {
|
||||
if ((mestate.vers == null) || (mestate.vers['AMT'] == null)) { console.log("Unable to get Intel AMT version."); exit(100); return; }
|
||||
if (mestate.ProvisioningState == null) { console.log("Unable to read Intel AMT activation state."); exit(100); return; }
|
||||
//if ((settings.action != 'amtdiscover') && (mestate.controlMode == 2)) { console.log("Intel AMT already activation in admin control mode."); exit(100); return; }
|
||||
if (mestate.uuid == null) { console.log("Unable to get Intel AMT UUID."); exit(100); return; }
|
||||
var fqdn = null;
|
||||
//if ((mestate.net0 == null) && (meinfo.net0.enabled != 0)) { console.log("No Intel AMT wired interface, can't perform ACM activation."); exit(100); return; }
|
||||
if (result) { fqdn = result; } // 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 != '')) { fqdn = interfaces[i][j].fqdn; }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fqdn != null) { settings.fqdn = fqdn; settings.uuid = mestate.uuid; }
|
||||
getTrustedHashes(amtMei, function () { startLms(configureAmt2, amtMei); });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function configureAmt2() {
|
||||
// Connect to MPS and start APF relay
|
||||
var apfarg = {
|
||||
mpsurl: settings.url,
|
||||
mpsuser: settings.id.substring(0, 16),
|
||||
mpspass: settings.id.substring(0, 16),
|
||||
mpskeepalive: 60000,
|
||||
clientname: require('os').hostname(),
|
||||
clientaddress: '127.0.0.1',
|
||||
clientuuid: mestate.uuid,
|
||||
conntype: 2 // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay.
|
||||
};
|
||||
if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
|
||||
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.onJsonControl = configureJsonControl;
|
||||
settings.apftunnel.onChannelClosed = function () { exit(0); }
|
||||
try {
|
||||
settings.apftunnel.connect();
|
||||
console.log("Started APF tunnel...");
|
||||
} catch (e) {
|
||||
console.log(JSON.stringify(e));
|
||||
exit(1); return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function configureJsonControl(data) {
|
||||
switch (data.action) {
|
||||
case 'console':
|
||||
console.log(data.msg);
|
||||
break;
|
||||
case 'close':
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Deactivate Intel AMT CCM
|
||||
//
|
||||
|
@ -2563,7 +2563,7 @@ function createMeshCore(agent) {
|
||||
var response = null;
|
||||
switch (cmd) {
|
||||
case 'help': { // Displays available commands
|
||||
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,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper,agentmsg';
|
||||
var fin = '', f = '', availcommands = 'amtconfig,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,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper,agentmsg';
|
||||
if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration,uac'; }
|
||||
if (process.platform != 'freebsd') { availcommands += ',vm';}
|
||||
if (require('MeshAgent').maxKvmTileSize != null) { availcommands += ',kvmmode'; }
|
||||
@ -3540,6 +3540,29 @@ function createMeshCore(agent) {
|
||||
if (diag) { diag.close(); diag = null; }
|
||||
break;
|
||||
}
|
||||
case 'amtconfig': {
|
||||
if (meshCoreObj.intelamt == null) { response = "No Intel AMT support delected"; break; }
|
||||
if (apftunnel != null) { response = "Intel AMT server tunnel already active"; break; }
|
||||
var apfarg = {
|
||||
mpsurl: mesh.ServerUrl.replace('agent.ashx', 'apf.ashx'),
|
||||
mpsuser: Buffer.from(mesh.ServerInfo.MeshID, 'hex').toString('base64').substring(0, 16),
|
||||
mpspass: Buffer.from(mesh.ServerInfo.MeshID, 'hex').toString('base64').substring(0, 16),
|
||||
mpskeepalive: 60000,
|
||||
clientname: require('os').hostname(),
|
||||
clientaddress: '127.0.0.1',
|
||||
clientuuid: meshCoreObj.intelamt.uuid,
|
||||
conntype: 2 // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay, other values for testing.
|
||||
};
|
||||
if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) { response = "Unable to get Intel AMT UUID"; break; }
|
||||
apftunnel = require('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; }
|
||||
}
|
||||
apftunnel.onChannelClosed = function () { apftunnel = null; }
|
||||
try { apftunnel.connect(); response = "Started Intel AMT configuration"; } catch (ex) { response = JSON.stringify(ex); }
|
||||
break;
|
||||
}
|
||||
case 'apf': {
|
||||
if (meshCoreObj.intelamt !== null) {
|
||||
if (args['_'].length == 1) {
|
||||
@ -3562,8 +3585,12 @@ function createMeshCore(agent) {
|
||||
if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
|
||||
response = "Unable to get Intel AMT UUID: " + apfarg.clientuuid;
|
||||
} else {
|
||||
var tobj = { debug: false };
|
||||
apftunnel = require('apfclient')(tobj, apfarg);
|
||||
apftunnel = require('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; }
|
||||
}
|
||||
apftunnel.onChannelClosed = function () { apftunnel = null; }
|
||||
try {
|
||||
apftunnel.connect();
|
||||
response = "Started APF tunnel";
|
||||
|
450
agents/modules_meshcmd/apfclient.js
Normal file
450
agents/modules_meshcmd/apfclient.js
Normal file
@ -0,0 +1,450 @@
|
||||
/*
|
||||
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 } ); }
|
||||
SendProtocolVersion(obj.forwardClient.ws, obj.args.clientuuid);
|
||||
SendServiceRequest(obj.forwardClient.ws, 'auth@amt.intel.com');
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
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;
|
@ -35,6 +35,9 @@ function CreateAPFClient(parent, args) {
|
||||
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); };
|
||||
@ -139,16 +142,14 @@ function CreateAPFClient(parent, args) {
|
||||
}
|
||||
|
||||
obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
|
||||
//Debug("APF Secure WebSocket connected.");
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
@ -159,21 +160,16 @@ function CreateAPFClient(parent, args) {
|
||||
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.");
|
||||
Debug("APF: in a failed state, destroying socket.");
|
||||
obj.forwardClient.ws.end();
|
||||
}
|
||||
} while (len > 0);
|
||||
} catch (e) {
|
||||
Debug(e);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
Debug("APF: Connection error, ending connecting.");
|
||||
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
|
||||
});
|
||||
|
||||
obj.state = CIRASTATE.INITIAL;
|
||||
@ -185,20 +181,20 @@ function CreateAPFClient(parent, args) {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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') {
|
||||
@ -213,7 +209,7 @@ function CreateAPFClient(parent, args) {
|
||||
data += IntToStr(8) + 'password';
|
||||
data += binzerostring(1) + IntToStr(pass.length) + pass;
|
||||
socket.write(data);
|
||||
//Debug("APF: Send username password authentication to MPS");
|
||||
Debug("APF: Send username password authentication to MPS");
|
||||
obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
|
||||
}
|
||||
|
||||
@ -222,18 +218,18 @@ function CreateAPFClient(parent, args) {
|
||||
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);
|
||||
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");
|
||||
Debug("APF: Send keepalive request");
|
||||
}
|
||||
|
||||
function SendKeepAliveReply(socket, cookie) {
|
||||
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie));
|
||||
//Debug("APF: Send keepalive reply");
|
||||
Debug("APF: Send keepalive reply");
|
||||
}
|
||||
|
||||
function ProcessData(socket) {
|
||||
@ -246,7 +242,7 @@ function CreateAPFClient(parent, args) {
|
||||
switch (cmd) {
|
||||
case APFProtocol.SERVICE_ACCEPT: {
|
||||
var slen = ReadInt(data, 1), service = data.substring(5, 6 + slen);
|
||||
//Debug("APF: Service request to " + service + " accepted.");
|
||||
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);
|
||||
@ -261,47 +257,47 @@ function CreateAPFClient(parent, args) {
|
||||
case APFProtocol.REQUEST_SUCCESS: {
|
||||
if (len >= 5) {
|
||||
var port = ReadInt(data, 1);
|
||||
//Debug("APF: Request to port forward " + port + " successful.");
|
||||
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.");
|
||||
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.");
|
||||
Debug("APF: Request successful.");
|
||||
return 1;
|
||||
}
|
||||
case APFProtocol.USERAUTH_SUCCESS: {
|
||||
//Debug("APF: User Authentication successful");
|
||||
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");
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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
|
||||
@ -322,21 +318,15 @@ function CreateAPFClient(parent, args) {
|
||||
});
|
||||
|
||||
chan.on('error', function (e) {
|
||||
//Debug("Downlink connection error: " + e);
|
||||
Debug("Downlink connection error: " + e);
|
||||
});
|
||||
|
||||
chan.on('end', function () {
|
||||
var chan = obj.downlinks[p_res.sender_chan];
|
||||
if (chan != null) {
|
||||
try {
|
||||
//Debug("Socket ends.");
|
||||
SendChannelClose(socket.ws, p_res.sender_chan);
|
||||
chan.xclosed = 1;
|
||||
// Add some delay before removing... otherwise race condition
|
||||
setTimeout(function () { delete obj.downlinks[p_res.sender_chan]; }, 100);
|
||||
} catch (e) {
|
||||
//Debug("Downlink connection exception: " + e);
|
||||
}
|
||||
Debug("Socket ends.");
|
||||
try { SendChannelClose(socket.ws, p_res.sender_chan); } catch (ex) { }
|
||||
delete obj.downlinks[p_res.sender_chan];
|
||||
}
|
||||
});
|
||||
|
||||
@ -348,22 +338,17 @@ function CreateAPFClient(parent, args) {
|
||||
return p_res.len;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
|
||||
//Debug("APF: 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);
|
||||
var chan = obj.downlinks[rcpt_chan];
|
||||
if ((chan != null) && (chan.xclosed !== 1)) {
|
||||
SendChannelClose(socket.ws, rcpt_chan);
|
||||
try { obj.downlinks[rcpt_chan].end(); } catch (e) { }
|
||||
delete obj.downlinks[rcpt_chan];
|
||||
}
|
||||
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)));
|
||||
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);
|
||||
@ -372,22 +357,26 @@ function CreateAPFClient(parent, args) {
|
||||
chan.curInWindow += chan_data_len;
|
||||
try {
|
||||
chan.write(Buffer.from(chan_data, 'binary'), function () {
|
||||
//Debug("Write completed.");
|
||||
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 (e) {
|
||||
//Debug("Cannot forward data to downlink socket.");
|
||||
}
|
||||
} catch (ex) { Debug("Cannot forward data to downlink socket."); }
|
||||
}
|
||||
return 9 + chan_data_len;
|
||||
}
|
||||
case APFProtocol.CHANNEL_WINDOW_ADJUST: {
|
||||
//Debug("APF: 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.");
|
||||
Debug("CMD: " + cmd + " is not implemented.");
|
||||
obj.cirastate = CIRASTATE.FAILED;
|
||||
return 0;
|
||||
}
|
||||
@ -412,36 +401,32 @@ function CreateAPFClient(parent, args) {
|
||||
|
||||
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");
|
||||
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");
|
||||
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: " + rstr2hex(data));
|
||||
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: " + rstr2hex(buf));
|
||||
Debug("APF: Send ChannelData: " + data.toString('hex'));
|
||||
}
|
||||
|
||||
function SendChannelClose(socket, chan) {
|
||||
socket.write(String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan));
|
||||
//Debug("APF: Send ChannelClose ");
|
||||
Debug("APF: Send ChannelClose ");
|
||||
}
|
||||
|
||||
obj.connect = function () {
|
||||
if (obj.forwardClient != null) {
|
||||
try {
|
||||
obj.forwardClient.ws.end();
|
||||
} catch (e) {
|
||||
Debug(e);
|
||||
}
|
||||
try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); }
|
||||
//obj.forwardClient = null;
|
||||
}
|
||||
obj.cirastate = CIRASTATE.INITIAL;
|
||||
@ -457,7 +442,7 @@ function CreateAPFClient(parent, args) {
|
||||
obj.forwardClient.end(); // end request, trigger completion of HTTP request
|
||||
}
|
||||
|
||||
obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (e) { Debug(e); } }
|
||||
obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); } }
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -240,19 +240,17 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
|
||||
if (state == 2) {
|
||||
// TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
|
||||
var options = { socket: ser, ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false };
|
||||
if (obj.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; }
|
||||
if (obj.xtlsMethod == 1) { options.secureProtocol = 'TLSv1_method'; }
|
||||
if (obj.xtlsoptions) {
|
||||
if (obj.xtlsoptions.ca) options.ca = obj.xtlsoptions.ca;
|
||||
if (obj.xtlsoptions.cert) options.cert = obj.xtlsoptions.cert;
|
||||
if (obj.xtlsoptions.key) options.key = obj.xtlsoptions.key;
|
||||
}
|
||||
|
||||
//obj.socket = new TLSSocket(ser, options);
|
||||
obj.socket = obj.tls.connect(obj.port, obj.host, options, obj.xxOnSocketConnected);
|
||||
obj.socket.setEncoding('binary');
|
||||
obj.socket.setTimeout(6000); // Set socket idle timeout
|
||||
obj.socket.on('error', function (err) { console.log("CIRA TLS Connection Error ", err); obj.xxOnSocketClosed(); });
|
||||
//obj.socket.on('error', function (e) { if (e.message && e.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } });
|
||||
obj.socket.on('error', function (ex) { obj.xtlsMethod = 1 - obj.xtlsMethod; });
|
||||
obj.socket.on('close', obj.xxOnSocketClosed);
|
||||
obj.socket.on('timeout', obj.xxOnSocketTimeout);
|
||||
|
||||
|
@ -76,6 +76,9 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
// Remove the device from the list
|
||||
devices.splice(i, 1);
|
||||
if (devices.length == 0) { delete obj.amtDevices[dev.nodeid]; } else { obj.amtDevices[dev.nodeid] = devices; }
|
||||
|
||||
// Notify connection closure if this is a LMS connection
|
||||
if (dev.connType == 2) { dev.controlMsg({ action: "close" }); }
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -103,9 +106,13 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
var devices = obj.amtDevices[nodeid], dev = null;
|
||||
if (devices != null) { for (var i in devices) { if ((devices[i].mpsConnection == connection) || (devices[i].host == connection)) { dev = devices[i]; } } }
|
||||
if (dev != null) return false; // We are already managing this device on this connection
|
||||
dev = { nodeid: nodeid, connType: connType };
|
||||
dev = { nodeid: nodeid, connType: connType, domainid: nodeid.split('/')[1] };
|
||||
if (typeof connection == 'string') { dev.host = connection; }
|
||||
if (typeof connection == 'object') { dev.mpsConnection = connection; }
|
||||
dev.consoleMsg = function deviceConsoleMsg(msg) { if (typeof deviceConsoleMsg.conn == 'object') { deviceConsoleMsg.conn.ControlMsg({ action: 'console', msg: msg }); } }
|
||||
dev.consoleMsg.conn = connection;
|
||||
dev.controlMsg = function deviceControlMsg(msg) { if (typeof deviceControlMsg.conn == 'object') { deviceControlMsg.conn.ControlMsg(msg); } }
|
||||
dev.controlMsg.conn = connection;
|
||||
parent.debug('amt', "Start Management", nodeid, connType);
|
||||
addAmtDevice(dev);
|
||||
fetchIntelAmtInformation(dev);
|
||||
@ -192,6 +199,7 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
//if (node.host) { dev.host = node.host.toLowerCase(); }
|
||||
dev.meshid = node.meshid;
|
||||
dev.intelamt = node.intelamt;
|
||||
dev.consoleMsg("Attempting Intel AMT connection...");
|
||||
attemptInitialContact(dev);
|
||||
});
|
||||
}
|
||||
@ -201,7 +209,7 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
parent.debug('amt', "Attempt Initial Contact", dev.name, dev.connType);
|
||||
|
||||
if ((dev.acctry == null) && ((typeof dev.intelamt.user != 'string') || (typeof dev.intelamt.pass != 'string'))) {
|
||||
if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { return; }
|
||||
if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { removeAmtDevice(dev); return; }
|
||||
}
|
||||
|
||||
switch (dev.connType) {
|
||||
@ -315,6 +323,7 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
// Check the response
|
||||
if ((status == 200) && (responses['AMT_GeneralSettings'] != null) && (responses['IPS_HostBasedSetupService'] != null) && (responses['IPS_HostBasedSetupService'].response != null) && (responses['IPS_HostBasedSetupService'].response != null) && (stack.wsman.comm.digestRealm == responses['AMT_GeneralSettings'].response.DigestRealm)) {
|
||||
// Everything looks good
|
||||
dev.consoleMsg(stack.wsman.comm.xtls ? "Intel AMT connected with TLS." : "Intel AMT connected.");
|
||||
dev.state = 1;
|
||||
if (dev.aquired == null) { dev.aquired = {}; }
|
||||
dev.aquired.controlMode = responses['IPS_HostBasedSetupService'].response.CurrentControlMode; // 1 = CCM, 2 = ACM
|
||||
@ -330,15 +339,20 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
|
||||
// Perform Intel AMT clock sync
|
||||
attemptSyncClock(dev, function () {
|
||||
attemptFetchHardwareInventory(dev); // See if we need to get hardware inventory
|
||||
|
||||
if (dev.connType != 2) {
|
||||
// Start power polling if not connected to LMS
|
||||
var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); }
|
||||
ppfunc.dev = dev;
|
||||
dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds.
|
||||
fetchPowerState(dev);
|
||||
}
|
||||
// See if we need to get hardware inventory
|
||||
attemptFetchHardwareInventory(dev, function () {
|
||||
dev.consoleMsg('Done.');
|
||||
if (dev.connType != 2) {
|
||||
// Start power polling if not connected to LMS
|
||||
var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); }
|
||||
ppfunc.dev = dev;
|
||||
dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds.
|
||||
fetchPowerState(dev);
|
||||
} else {
|
||||
// For LMS connections, close now.
|
||||
dev.controlMsg({ action: "close" });
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// We got a bad response
|
||||
@ -509,7 +523,8 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
// Care should be take not to have many pending WSMAN called when performing clock sync.
|
||||
function attemptSyncClock(dev, func) {
|
||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||
dev.clockSyncCompleted = func;
|
||||
dev.taskCount = 1;
|
||||
dev.taskCompleted = func;
|
||||
dev.amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(attemptSyncClockEx);
|
||||
}
|
||||
|
||||
@ -517,17 +532,19 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
function attemptSyncClockEx(stack, name, response, status) {
|
||||
const dev = stack.dev;
|
||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||
if (status != 200) { removeDevice(dev.nodeid); }
|
||||
if (status != 200) { removeDevice(dev.nodeid); return; }
|
||||
|
||||
// Compute how much drift between Intel AMT and our clock.
|
||||
var t = new Date(), now = new Date();
|
||||
t.setTime(response.Body['Ta0'] * 1000);
|
||||
if (Math.abs(t - now) > 10000) { // If the Intel AMT clock is more than 10 seconds off, set it.
|
||||
dev.consoleMsg("Performing clock sync.");
|
||||
var Tm1 = Math.round(now.getTime() / 1000);
|
||||
dev.amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, attemptSyncClockSet);
|
||||
} else {
|
||||
// Clock is fine, we are done.
|
||||
if (dev.clockSyncCompleted != null) { var f = dev.clockSyncCompleted; delete dev.clockSyncCompleted; f(); }
|
||||
dev.consoleMsg("Clock ok.");
|
||||
devTaskCompleted(dev)
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,28 +553,37 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
const dev = stack.dev;
|
||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||
if (status != 200) { removeDevice(dev.nodeid); }
|
||||
if (dev.clockSyncCompleted != null) { var f = dev.clockSyncCompleted; delete dev.clockSyncCompleted; f(); }
|
||||
devTaskCompleted(dev)
|
||||
}
|
||||
|
||||
function attemptFetchHardwareInventory(dev) {
|
||||
if (obj.amtDevices[dev.nodeid] == null) return false; // Device no longer exists, ignore this request.
|
||||
function attemptFetchHardwareInventory(dev, func) {
|
||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||
const mesh = parent.webserver.meshes[dev.meshid];
|
||||
if (mesh == null) { removeDevice(dev.nodeid); return false; }
|
||||
if (mesh == null) { removeDevice(dev.nodeid); return; }
|
||||
if (mesh.mtype == 1) { // If this is a Intel AMT only device group, pull the hardware inventory and network information for this device
|
||||
dev.consoleMsg("Fetching hardware inventory.");
|
||||
dev.taskCount = 2;
|
||||
dev.taskCompleted = func;
|
||||
dev.amtstack.BatchEnum('', ['*CIM_ComputerSystemPackage', 'CIM_SystemPackaging', '*CIM_Chassis', 'CIM_Chip', '*CIM_Card', '*CIM_BIOSElement', 'CIM_Processor', 'CIM_PhysicalMemory', 'CIM_MediaAccessDevice', 'CIM_PhysicalPackage'], attemptFetchHardwareInventoryResponse);
|
||||
dev.amtstack.BatchEnum('', ['AMT_EthernetPortSettings'], attemptFetchNetworkResponse);
|
||||
return true;
|
||||
} else {
|
||||
if (func) { func(); }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
function devTaskCompleted(dev) {
|
||||
dev.taskCount--;
|
||||
if (dev.taskCount == 0) { var f = dev.taskCompleted; delete dev.taskCount; delete dev.taskCompleted; if (f != null) { f(); } }
|
||||
}
|
||||
|
||||
function attemptFetchNetworkResponse(stack, name, responses, status) {
|
||||
const dev = stack.dev;
|
||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||
if (status != 200) return;
|
||||
if (status != 200) { devTaskCompleted(dev); return; }
|
||||
|
||||
//console.log(JSON.stringify(responses, null, 2));
|
||||
if ((responses['AMT_EthernetPortSettings'] == null) || (responses['AMT_EthernetPortSettings'].responses == null)) return;
|
||||
if ((responses['AMT_EthernetPortSettings'] == null) || (responses['AMT_EthernetPortSettings'].responses == null)) { devTaskCompleted(dev); return; }
|
||||
|
||||
// Find the wired and wireless interfaces
|
||||
var wired = null, wireless = null;
|
||||
@ -567,7 +593,7 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
if (netif.WLANLinkProtectionLevel != null) { wireless = netif; } else { wired = netif; }
|
||||
}
|
||||
}
|
||||
if ((wired == null) && (wireless == null)) return;
|
||||
if ((wired == null) && (wireless == null)) { devTaskCompleted(dev); return; }
|
||||
|
||||
// Sent by the agent to update agent network interface information
|
||||
var net = { netif2: {} };
|
||||
@ -601,6 +627,8 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
|
||||
// Event the node interface information change
|
||||
parent.DispatchEvent(parent.webserver.CreateMeshDispatchTargets(dev.meshid, [dev.nodeid]), obj, { action: 'ifchange', nodeid: dev.nodeid, domain: dev.nodeid.split('/')[1], nolog: 1 });
|
||||
|
||||
devTaskCompleted(dev);
|
||||
}
|
||||
|
||||
|
||||
@ -625,7 +653,7 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
function attemptFetchHardwareInventoryResponse(stack, name, responses, status) {
|
||||
const dev = stack.dev;
|
||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||
if (status != 200) return;
|
||||
if (status != 200) { devTaskCompleted(dev); return; }
|
||||
|
||||
// Extract basic data
|
||||
var hw = {}
|
||||
@ -648,9 +676,11 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
var m2 = {}, m = hw.PhysicalMemory[i];
|
||||
m2.BankLabel = m.BankLabel;
|
||||
m2.Capacity = m.Capacity;
|
||||
m2.PartNumber = m.PartNumber.trim();
|
||||
m2.SerialNumber = m.SerialNumber.trim();
|
||||
m2.Manufacturer = m.Manufacturer.trim();
|
||||
if (m.PartNumber) { m2.PartNumber = m.PartNumber.trim(); }
|
||||
if (typeof m.SerialNumber == 'string') { m2.SerialNumber = m.SerialNumber.trim(); }
|
||||
if (typeof m.SerialNumber == 'number') { m2.SerialNumber = m.SerialNumber; }
|
||||
if (typeof m.SerialNumber == 'string') { m2.Manufacturer = m.Manufacturer.trim(); }
|
||||
if (typeof m.Manufacturer == 'number') { m2.Manufacturer = m.Manufacturer; }
|
||||
memory.push(m2);
|
||||
}
|
||||
hw2.hardware.windows.memory = memory;
|
||||
@ -660,21 +690,21 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
for (var i in hw.MediaAccessDevice) {
|
||||
var m2 = {}, m = hw.MediaAccessDevice[i];
|
||||
m2.Caption = m.DeviceID;
|
||||
m2.Size = (m.MaxMediaSize * 1000);
|
||||
if (m.MaxMediaSize) { m2.Size = (m.MaxMediaSize * 1000); }
|
||||
drives.push(m2);
|
||||
}
|
||||
hw2.hardware.identifiers.storage_devices = drives;
|
||||
}
|
||||
if (hw.Bios != null) {
|
||||
hw2.hardware.identifiers.bios_vendor = hw.Bios.Manufacturer.trim();
|
||||
if (hw.Bios.Manufacturer) { hw2.hardware.identifiers.bios_vendor = hw.Bios.Manufacturer.trim(); }
|
||||
hw2.hardware.identifiers.bios_version = hw.Bios.Version;
|
||||
if (hw.Bios.ReleaseDate && hw.Bios.ReleaseDate.Datetime) { hw2.hardware.identifiers.bios_date = hw.Bios.ReleaseDate.Datetime; }
|
||||
}
|
||||
if (hw.PhysicalPackage != null) {
|
||||
hw2.hardware.identifiers.board_name = hw.Card.Model.trim();
|
||||
hw2.hardware.identifiers.board_vendor = hw.Card.Manufacturer.trim();
|
||||
hw2.hardware.identifiers.board_version = hw.Card.Version.trim();
|
||||
hw2.hardware.identifiers.board_serial = hw.Card.SerialNumber.trim();
|
||||
if (hw.Card.Model) { hw2.hardware.identifiers.board_name = hw.Card.Model.trim(); }
|
||||
if (hw.Card.Manufacturer) { hw2.hardware.identifiers.board_vendor = hw.Card.Manufacturer.trim(); }
|
||||
if (hw.Card.Version) { hw2.hardware.identifiers.board_version = hw.Card.Version.trim(); }
|
||||
if (hw.Card.SerialNumber) { hw2.hardware.identifiers.board_serial = hw.Card.SerialNumber.trim(); }
|
||||
}
|
||||
if ((hw.Chips != null) && (hw.Chips.length > 0)) {
|
||||
for (var i in hw.Chips) {
|
||||
@ -704,6 +734,8 @@ module.exports.CreateAmtManager = function(parent) {
|
||||
parent.DispatchEvent(parent.webserver.CreateMeshDispatchTargets(dev.meshid, [dev.nodeid]), obj, event);
|
||||
}
|
||||
});
|
||||
|
||||
devTaskCompleted(dev);
|
||||
}
|
||||
|
||||
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); }
|
||||
|
10
mpsserver.js
10
mpsserver.js
@ -285,6 +285,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
socket.SetupChannel.parent = obj;
|
||||
socket.SetupChannel.conn = socket;
|
||||
socket.websocket = 1;
|
||||
socket.ControlMsg = function ControlMsg(message) { return ControlMsg.parent.SendJsonControl(ControlMsg.conn, message); }
|
||||
socket.ControlMsg.parent = obj;
|
||||
socket.ControlMsg.conn = socket;
|
||||
parent.debug('mps', "New CIRA websocket connection");
|
||||
|
||||
socket.on('message', function (data) {
|
||||
@ -913,6 +916,13 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
for (var i in connections) { obj.close(connections[i]); }
|
||||
};
|
||||
|
||||
obj.SendJsonControl = function(socket, data) {
|
||||
if (socket.tag.connType == 0) return; // This command is valid only for connections that are not really CIRA.
|
||||
parent.debug('mpscmd', '<-- JSON_CONTROL');
|
||||
if (typeof data == 'object') { data = JSON.stringify(data); }
|
||||
Write(socket, String.fromCharCode(APFProtocol.JSON_CONTROL) + common.IntToStr(data.length) + data);
|
||||
}
|
||||
|
||||
function SendServiceAccept(socket, service) {
|
||||
parent.debug('mpscmd', '<-- SERVICE_ACCEPT', service);
|
||||
Write(socket, String.fromCharCode(APFProtocol.SERVICE_ACCEPT) + common.IntToStr(service.length) + service);
|
||||
|
@ -3520,6 +3520,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (ws.logfile != null) { recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, ws) { obj.fs.close(fd); delete ws.logfile; }, ws); }
|
||||
});
|
||||
|
||||
// Note that here, req.query.p: 1 = WSMAN with server auth, 2 = REDIR with server auth, 3 = WSMAN without server auth, 4 = REDIR with server auth
|
||||
|
||||
// Fetch Intel AMT credentials & Setup interceptor
|
||||
if (req.query.p == 1) {
|
||||
parent.debug('webrelaydata', 'INTERCEPTOR1', { host: node.host, port: port, user: node.intelamt.user, pass: node.intelamt.pass });
|
||||
@ -3587,7 +3589,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
// Compute target port
|
||||
var port = 16992;
|
||||
if (node.intelamt.tls > 0) port = 16993; // This is a direct connection, use TLS when possible
|
||||
if (req.query.p == 2) port += 2;
|
||||
if ((req.query.p == 2) || (req.query.p == 4)) port += 2;
|
||||
|
||||
if (node.intelamt.tls == 0) {
|
||||
// If this is TCP (without TLS) set a normal TCP socket
|
||||
|
Loading…
Reference in New Issue
Block a user