Added Intel AMT tunneling configuration support.
Ylian Saint-Hilaire committed
Oct 17, 2020 at 19:23 UTC
fd8265313d107bc1bb2251567de62bc9dcd28c12
8 files changed
+709
-109
agents/meshcmd.js
+97
-1
@@ -113,7 +113,7 @@ function run(argv) {
113
//console.log('addedModules = ' + JSON.stringify(addedModules));
114
var actionpath = 'meshaction.txt';
115
if (args.actionfile != null) { actionpath = args.actionfile; }
116
- 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'];
116
+ 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'];
117
118
// Load the action file
119
var actionfile = null;
@@ -129,6 +129,7 @@ function run(argv) {
129
if ((typeof args.localport) == 'string') { settings.localport = parseInt(args.localport); }
130
if ((typeof args.remotenodeid) == 'string') { settings.remotenodeid = args.remotenodeid; }
131
if ((typeof args.name) == 'string') { settings.name = args.name; }
132
+ if ((typeof args.id) == 'string') { settings.id = args.id; }
133
if ((typeof args.username) == 'string') { settings.username = args.username; }
134
if ((typeof args.password) == 'string') { settings.password = args.password; }
135
if ((typeof args.url) == 'string') { settings.url = args.url; }
@@ -174,6 +175,7 @@ function run(argv) {
175
console.log(' meshcmd [action] [arguments...]\r\n');
176
console.log('Valid MeshCentral actions:');
177
console.log(' Route - Map a local TCP port to a remote computer.');
178
+ console.log(' AmtConfig - Setup Intel AMT on this computer.');
179
console.log('\r\nValid local actions:');
180
console.log(' SMBios - Display System Management BIOS tables for this computer.');
181
console.log(' RawSMBios - Display RAW System Management BIOS tables for this computer.');
@@ -245,6 +247,12 @@ function run(argv) {
247
console.log(' --tag [string] Optional string sent to the server during activation.');
248
console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.');
249
console.log(' --profile [string] Optional profile used for server activation.');
250
+ } else if (action == 'amtconfig') {
251
+ 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]');
252
+ console.log('\r\nPossible arguments:\r\n');
253
+ console.log(' --url [wss://server] The address of the MeshCentral server.');
254
+ console.log(' --id [groupid] The device group identifier.');
255
+ console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.');
256
} else if (action == 'amtacm') {
257
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]');
258
console.log('\r\nPossible arguments:\r\n');
@@ -643,6 +651,12 @@ function run(argv) {
651
settings.localport = 16992;
652
debug(1, "Settings: " + JSON.stringify(settings));
653
getAmtUuid();
654
+ } else if (settings.action == 'amtconfig') {
655
+ // Start Intel AMT configuration
656
+ if ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == '')) { console.log('No MeshCentral server URL specified, use --url [url].'); exit(1); return; }
657
+ if ((settings.id == null) || (typeof settings.id != 'string') || (settings.id == '')) { console.log('No device group identifier specified, use --id [identifier].'); exit(1); return; }
658
+ debug(1, "Settings: " + JSON.stringify(settings));
659
+ configureAmt();
660
} else if (settings.action == 'amtccm') {
661
// Start activation to CCM
662
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() {
1141
}
1142
1143
1144
+//
1145
+// Configure Intel AMT
1146
+//
1147
+
1148
+function configureAmt() {
1149
+ console.log('Starting Intel AMT configuration...');
1150
+ settings.noconsole = true;
1151
+
1152
+ // Display Intel AMT version and activation state
1153
+ mestate = {};
1154
+ var amtMeiModule, amtMei;
1155
+ try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { console.log(ex); exit(1); return; }
1156
+ amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; });
1157
+ amtMei.getProvisioningState(function (result) { if (result) { mestate.ProvisioningState = result; } });
1158
+ 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; } } });
1159
+ amtMei.getLanInterfaceSettings(0, function (result) { if (result) { mestate.net0 = result; } });
1160
+ amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } });
1161
+ amtMei.getControlMode(function (result) { if (result != null) { mestate.controlMode = result.controlMode; } }); // controlMode: 0 = NoActivated, 1 = CCM, 2 = ACM
1162
+ amtMei.getDnsSuffix(function (result) {
1163
+ if ((mestate.vers == null) || (mestate.vers['AMT'] == null)) { console.log("Unable to get Intel AMT version."); exit(100); return; }
1164
+ if (mestate.ProvisioningState == null) { console.log("Unable to read Intel AMT activation state."); exit(100); return; }
1165
+ //if ((settings.action != 'amtdiscover') && (mestate.controlMode == 2)) { console.log("Intel AMT already activation in admin control mode."); exit(100); return; }
1166
+ if (mestate.uuid == null) { console.log("Unable to get Intel AMT UUID."); exit(100); return; }
1167
+ var fqdn = null;
1168
+ //if ((mestate.net0 == null) && (meinfo.net0.enabled != 0)) { console.log("No Intel AMT wired interface, can't perform ACM activation."); exit(100); return; }
1169
+ if (result) { fqdn = result; } // If Intel AMT has a trusted DNS suffix set, use that one.
1170
+ else {
1171
+ // Look for the DNS suffix for the Intel AMT Ethernet interface
1172
+ var interfaces = require('os').networkInterfaces();
1173
+ for (var i in interfaces) {
1174
+ for (var j in interfaces[i]) {
1175
+ if ((interfaces[i][j].mac == mestate.net0.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { fqdn = interfaces[i][j].fqdn; }
1176
+ }
1177
+ }
1178
+ }
1179
+ if (fqdn != null) { settings.fqdn = fqdn; settings.uuid = mestate.uuid; }
1180
+ getTrustedHashes(amtMei, function () { startLms(configureAmt2, amtMei); });
1181
+ });
1182
+
1183
+}
1184
+
1185
+function configureAmt2() {
1186
+ // Connect to MPS and start APF relay
1187
+ var apfarg = {
1188
+ mpsurl: settings.url,
1189
+ mpsuser: settings.id.substring(0, 16),
1190
+ mpspass: settings.id.substring(0, 16),
1191
+ mpskeepalive: 60000,
1192
+ clientname: require('os').hostname(),
1193
+ clientaddress: '127.0.0.1',
1194
+ clientuuid: mestate.uuid,
1195
+ conntype: 2 // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay.
1196
+ };
1197
+ if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
1198
+ console.log("Unable to get Intel AMT UUID: " + apfarg.clientuuid);
1199
+ exit(1); return;
1200
+ } else {
1201
+ settings.apftunnel = require('apfclient')({ debug: (settings.debuglevel > 0) }, apfarg);
1202
+ settings.apftunnel.onJsonControl = configureJsonControl;
1203
+ settings.apftunnel.onChannelClosed = function () { exit(0); }
1204
+ try {
1205
+ settings.apftunnel.connect();
1206
+ console.log("Started APF tunnel...");
1207
+ } catch (e) {
1208
+ console.log(JSON.stringify(e));
1209
+ exit(1); return;
1210
+ }
1211
+ }
1212
+}
1213
+
1214
+function configureJsonControl(data) {
1215
+ switch (data.action) {
1216
+ case 'console':
1217
+ console.log(data.msg);
1218
+ break;
1219
+ case 'close':
1220
+ exit(0);
1221
+ break;
1222
+ }
1223
+}
1224
+
1225
+
1226
//
1227
// Deactivate Intel AMT CCM
1228
//
agents/meshcore.js
+30
-3
@@ -2563,7 +2563,7 @@ function createMeshCore(agent) {
2563
var response = null;
2564
switch (cmd) {
2565
case 'help': { // Displays available commands
2566
- 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';
2566
+ 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';
2567
if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration,uac'; }
2568
if (process.platform != 'freebsd') { availcommands += ',vm';}
2569
if (require('MeshAgent').maxKvmTileSize != null) { availcommands += ',kvmmode'; }
@@ -3540,6 +3540,29 @@ function createMeshCore(agent) {
3540
if (diag) { diag.close(); diag = null; }
3541
break;
3542
}
3543
+ case 'amtconfig': {
3544
+ if (meshCoreObj.intelamt == null) { response = "No Intel AMT support delected"; break; }
3545
+ if (apftunnel != null) { response = "Intel AMT server tunnel already active"; break; }
3546
+ var apfarg = {
3547
+ mpsurl: mesh.ServerUrl.replace('agent.ashx', 'apf.ashx'),
3548
+ mpsuser: Buffer.from(mesh.ServerInfo.MeshID, 'hex').toString('base64').substring(0, 16),
3549
+ mpspass: Buffer.from(mesh.ServerInfo.MeshID, 'hex').toString('base64').substring(0, 16),
3550
+ mpskeepalive: 60000,
3551
+ clientname: require('os').hostname(),
3552
+ clientaddress: '127.0.0.1',
3553
+ clientuuid: meshCoreObj.intelamt.uuid,
3554
+ conntype: 2 // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay, other values for testing.
3555
+ };
3556
+ if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) { response = "Unable to get Intel AMT UUID"; break; }
3557
+ apftunnel = require('apfclient')({ debug: false }, apfarg);
3558
+ apftunnel.onJsonControl = function (data) {
3559
+ if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); }
3560
+ if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; }
3561
+ }
3562
+ apftunnel.onChannelClosed = function () { apftunnel = null; }
3563
+ try { apftunnel.connect(); response = "Started Intel AMT configuration"; } catch (ex) { response = JSON.stringify(ex); }
3564
+ break;
3565
+ }
3566
case 'apf': {
3567
if (meshCoreObj.intelamt !== null) {
3568
if (args['_'].length == 1) {
@@ -3562,8 +3585,12 @@ function createMeshCore(agent) {
3585
if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
3586
response = "Unable to get Intel AMT UUID: " + apfarg.clientuuid;
3587
} else {
3565
- var tobj = { debug: false };
3566
- apftunnel = require('apfclient')(tobj, apfarg);
3588
+ apftunnel = require('apfclient')({ debug: false }, apfarg);
3589
+ apftunnel.onJsonControl = function (data) {
3590
+ if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); }
3591
+ if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; }
3592
+ }
3593
+ apftunnel.onChannelClosed = function () { apftunnel = null; }
3594
try {
3595
apftunnel.connect();
3596
response = "Started APF tunnel";
agents/modules_meshcmd/apfclient.js
new
+450
@@ -0,0 +1,450 @@
1
+/*
2
+Copyright 2018-2020 Intel Corporation
3
+
4
+Licensed under the Apache License, Version 2.0 (the "License");
5
+you may not use this file except in compliance with the License.
6
+You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+Unless required by applicable law or agreed to in writing, software
11
+distributed under the License is distributed on an "AS IS" BASIS,
12
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+See the License for the specific language governing permissions and
14
+limitations under the License.
15
+*/
16
+
17
+/**
18
+* @description APF/CIRA Client for Duktape
19
+* @author Joko Sastriawan & Ylian Saint-Hilaire
20
+* @copyright Intel Corporation 2020
21
+* @license Apache-2.0
22
+* @version v0.0.2
23
+*/
24
+
25
+function CreateAPFClient(parent, args) {
26
+ if ((args.clientuuid == null) || (args.clientuuid.length != 36)) return null; // Require a UUID if this exact length
27
+
28
+ var obj = {};
29
+ obj.parent = parent;
30
+ obj.args = args;
31
+ obj.http = require('http');
32
+ obj.net = require('net');
33
+ obj.forwardClient = null;
34
+ obj.downlinks = {};
35
+ obj.pfwd_idx = 0;
36
+ obj.timer = null; // Keep alive timer
37
+
38
+ // obj.onChannelClosed
39
+ // obj.onJsonControl
40
+
41
+ // Function copied from common.js
42
+ 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.
43
+ function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); };
44
+ function hex2rstr(d) { var r = '', m = ('' + d).match(/../g), t; while (t = m.shift()) { r += String.fromCharCode('0x' + t); } return r; };
45
+ function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }; // Convert decimal to hex
46
+ 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
47
+ function d2h(d) { return (d / 256 + 1 / 512).toString(16).substring(2, 4); }
48
+ function buf2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += d2h(input[i]); } return r; };
49
+ function Debug(str) { if (obj.parent.debug) { console.log(str); } }
50
+ 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); }
51
+ 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; }
52
+ function binzerostring(len) { var res = ''; for (var l = 0; l < len; l++) { res += String.fromCharCode(0 & 0xFF); } return res; }
53
+
54
+ // CIRA state
55
+ var CIRASTATE = {
56
+ INITIAL: 0,
57
+ PROTOCOL_VERSION_SENT: 1,
58
+ AUTH_SERVICE_REQUEST_SENT: 2,
59
+ AUTH_REQUEST_SENT: 3,
60
+ PFWD_SERVICE_REQUEST_SENT: 4,
61
+ GLOBAL_REQUEST_SENT: 5,
62
+ FAILED: -1
63
+ }
64
+ obj.cirastate = CIRASTATE.INITIAL;
65
+
66
+ // REDIR state
67
+ var REDIR_TYPE = {
68
+ REDIR_UNKNOWN: 0,
69
+ REDIR_SOL: 1,
70
+ REDIR_KVM: 2,
71
+ REDIR_IDER: 3
72
+ }
73
+
74
+ // redirection start command
75
+ obj.RedirectStartSol = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20);
76
+ obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
77
+ obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
78
+
79
+ // Intel AMT forwarded port list for non-TLS mode
80
+ //var pfwd_ports = [16992, 623, 16994, 5900];
81
+ var pfwd_ports = [ 16992, 16993 ];
82
+
83
+ // protocol definitions
84
+ var APFProtocol = {
85
+ UNKNOWN: 0,
86
+ DISCONNECT: 1,
87
+ SERVICE_REQUEST: 5,
88
+ SERVICE_ACCEPT: 6,
89
+ USERAUTH_REQUEST: 50,
90
+ USERAUTH_FAILURE: 51,
91
+ USERAUTH_SUCCESS: 52,
92
+ GLOBAL_REQUEST: 80,
93
+ REQUEST_SUCCESS: 81,
94
+ REQUEST_FAILURE: 82,
95
+ CHANNEL_OPEN: 90,
96
+ CHANNEL_OPEN_CONFIRMATION: 91,
97
+ CHANNEL_OPEN_FAILURE: 92,
98
+ CHANNEL_WINDOW_ADJUST: 93,
99
+ CHANNEL_DATA: 94,
100
+ CHANNEL_CLOSE: 97,
101
+ PROTOCOLVERSION: 192,
102
+ KEEPALIVE_REQUEST: 208,
103
+ KEEPALIVE_REPLY: 209,
104
+ KEEPALIVE_OPTIONS_REQUEST: 210,
105
+ KEEPALIVE_OPTIONS_REPLY: 211,
106
+ JSON_CONTROL: 250 // This is a Mesh specific command that sends JSON to and from the MPS server.
107
+ }
108
+
109
+ var APFDisconnectCode = {
110
+ HOST_NOT_ALLOWED_TO_CONNECT: 1,
111
+ PROTOCOL_ERROR: 2,
112
+ KEY_EXCHANGE_FAILED: 3,
113
+ RESERVED: 4,
114
+ MAC_ERROR: 5,
115
+ COMPRESSION_ERROR: 6,
116
+ SERVICE_NOT_AVAILABLE: 7,
117
+ PROTOCOL_VERSION_NOT_SUPPORTED: 8,
118
+ HOST_KEY_NOT_VERIFIABLE: 9,
119
+ CONNECTION_LOST: 10,
120
+ BY_APPLICATION: 11,
121
+ TOO_MANY_CONNECTIONS: 12,
122
+ AUTH_CANCELLED_BY_USER: 13,
123
+ NO_MORE_AUTH_METHODS_AVAILABLE: 14,
124
+ INVALID_CREDENTIALS: 15,
125
+ CONNECTION_TIMED_OUT: 16,
126
+ BY_POLICY: 17,
127
+ TEMPORARILY_UNAVAILABLE: 18
128
+ }
129
+
130
+ var APFChannelOpenFailCodes = {
131
+ ADMINISTRATIVELY_PROHIBITED: 1,
132
+ CONNECT_FAILED: 2,
133
+ UNKNOWN_CHANNEL_TYPE: 3,
134
+ RESOURCE_SHORTAGE: 4,
135
+ }
136
+
137
+ var APFChannelOpenFailureReasonCode = {
138
+ AdministrativelyProhibited: 1,
139
+ ConnectFailed: 2,
140
+ UnknownChannelType: 3,
141
+ ResourceShortage: 4,
142
+ }
143
+
144
+ obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
145
+ Debug("APF Secure WebSocket connected.");
146
+ //console.log(JSON.stringify(resp));
147
+ obj.forwardClient.tag = { accumulator: [] };
148
+ obj.forwardClient.ws = ws;
149
+ obj.forwardClient.ws.on('end', function () {
150
+ Debug("APF: Connection is closing.");
151
+ if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
152
+ if (obj.onChannelClosed) { obj.onChannelClosed(obj); }
153
+ });
154
+
155
+ obj.forwardClient.ws.on('data', function (data) {
156
+ obj.forwardClient.tag.accumulator += hex2rstr(buf2hex(data));
157
+ try {
158
+ var len = 0;
159
+ do {
160
+ len = ProcessData(obj.forwardClient);
161
+ if (len > 0) { obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len); }
162
+ if (obj.cirastate == CIRASTATE.FAILED) {
163
+ Debug("APF: in a failed state, destroying socket.");
164
+ obj.forwardClient.ws.end();
165
+ }
166
+ } while (len > 0);
167
+ } catch (ex) { Debug(ex); }
168
+ });
169
+
170
+ obj.forwardClient.ws.on('error', function (e) {
171
+ Debug("APF: Connection error, ending connecting.");
172
+ if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
173
+ });
174
+
175
+ obj.state = CIRASTATE.INITIAL;
176
+ if ((typeof obj.args.conntype == 'number') && (obj.args.conntype != 0)) { SendJsonControl(obj.forwardClient.ws, { action: 'connType', value: obj.args.conntype } ); }
177
+ SendProtocolVersion(obj.forwardClient.ws, obj.args.clientuuid);
178
+ SendServiceRequest(obj.forwardClient.ws, 'auth@amt.intel.com');
179
+ }
180
+
181
+ function SendJsonControl(socket, o) {
182
+ var data = JSON.stringify(o)
183
+ socket.write(String.fromCharCode(APFProtocol.JSON_CONTROL) + IntToStr(data.length) + data);
184
+ Debug("APF: Send JSON control: " + data);
185
+ }
186
+
187
+ function SendProtocolVersion(socket, uuid) {
188
+ var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(strToGuid(uuid)) + binzerostring(64);
189
+ socket.write(data);
190
+ Debug("APF: Send protocol version 1 0 " + uuid);
191
+ obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
192
+ }
193
+
194
+ function SendServiceRequest(socket, service) {
195
+ var data = String.fromCharCode(APFProtocol.SERVICE_REQUEST) + IntToStr(service.length) + service;
196
+ socket.write(data);
197
+ Debug("APF: Send service request " + service);
198
+ if (service == 'auth@amt.intel.com') {
199
+ obj.cirastate = CIRASTATE.AUTH_SERVICE_REQUEST_SENT;
200
+ } else if (service == 'pfwd@amt.intel.com') {
201
+ obj.cirastate = CIRASTATE.PFWD_SERVICE_REQUEST_SENT;
202
+ }
203
+ }
204
+
205
+ function SendUserAuthRequest(socket, user, pass) {
206
+ var service = "pfwd@amt.intel.com";
207
+ var data = String.fromCharCode(APFProtocol.USERAUTH_REQUEST) + IntToStr(user.length) + user + IntToStr(service.length) + service;
208
+ //password auth
209
+ data += IntToStr(8) + 'password';
210
+ data += binzerostring(1) + IntToStr(pass.length) + pass;
211
+ socket.write(data);
212
+ Debug("APF: Send username password authentication to MPS");
213
+ obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
214
+ }
215
+
216
+ function SendGlobalRequestPfwd(socket, amthostname, amtport) {
217
+ var tcpipfwd = 'tcpip-forward';
218
+ var data = String.fromCharCode(APFProtocol.GLOBAL_REQUEST) + IntToStr(tcpipfwd.length) + tcpipfwd + binzerostring(1, 1);
219
+ data += IntToStr(amthostname.length) + amthostname + IntToStr(amtport);
220
+ socket.write(data);
221
+ Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
222
+ obj.cirastate = CIRASTATE.GLOBAL_REQUEST_SENT;
223
+ }
224
+
225
+ function SendKeepAliveRequest(socket) {
226
+ socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255));
227
+ Debug("APF: Send keepalive request");
228
+ }
229
+
230
+ function SendKeepAliveReply(socket, cookie) {
231
+ socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie));
232
+ Debug("APF: Send keepalive reply");
233
+ }
234
+
235
+ function ProcessData(socket) {
236
+ var cmd = socket.tag.accumulator.charCodeAt(0);
237
+ var len = socket.tag.accumulator.length;
238
+ var data = socket.tag.accumulator;
239
+ if (len == 0) { return 0; }
240
+
241
+ // Respond to MPS according to obj.cirastate
242
+ switch (cmd) {
243
+ case APFProtocol.SERVICE_ACCEPT: {
244
+ var slen = ReadInt(data, 1), service = data.substring(5, 6 + slen);
245
+ Debug("APF: Service request to " + service + " accepted.");
246
+ if (service == 'auth@amt.intel.com') {
247
+ if (obj.cirastate >= CIRASTATE.AUTH_SERVICE_REQUEST_SENT) {
248
+ SendUserAuthRequest(socket.ws, obj.args.mpsuser, obj.args.mpspass);
249
+ }
250
+ } else if (service == 'pfwd@amt.intel.com') {
251
+ if (obj.cirastate >= CIRASTATE.PFWD_SERVICE_REQUEST_SENT) {
252
+ SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
253
+ }
254
+ }
255
+ return 5 + slen;
256
+ }
257
+ case APFProtocol.REQUEST_SUCCESS: {
258
+ if (len >= 5) {
259
+ var port = ReadInt(data, 1);
260
+ Debug("APF: Request to port forward " + port + " successful.");
261
+ // iterate to pending port forward request
262
+ if (obj.pfwd_idx < pfwd_ports.length) {
263
+ SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
264
+ } else {
265
+ // no more port forward, now setup timer to send keep alive
266
+ Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
267
+ obj.timer = setInterval(function () {
268
+ SendKeepAliveRequest(obj.forwardClient.ws);
269
+ }, obj.args.mpskeepalive);//
270
+ }
271
+ return 5;
272
+ }
273
+ Debug("APF: Request successful.");
274
+ return 1;
275
+ }
276
+ case APFProtocol.USERAUTH_SUCCESS: {
277
+ Debug("APF: User Authentication successful");
278
+ // Send Pfwd service request
279
+ SendServiceRequest(socket.ws, 'pfwd@amt.intel.com');
280
+ return 1;
281
+ }
282
+ case APFProtocol.USERAUTH_FAILURE: {
283
+ Debug("APF: User Authentication failed");
284
+ obj.cirastate = CIRASTATE.FAILED;
285
+ return 14;
286
+ }
287
+ case APFProtocol.KEEPALIVE_REQUEST: {
288
+ Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
289
+ SendKeepAliveReply(socket.ws, ReadInt(data, 1));
290
+ return 5;
291
+ }
292
+ case APFProtocol.KEEPALIVE_REPLY: {
293
+ Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
294
+ return 5;
295
+ }
296
+ // Channel management
297
+ case APFProtocol.CHANNEL_OPEN: {
298
+ // Parse CHANNEL OPEN request
299
+ var p_res = parseChannelOpen(data);
300
+ Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
301
+ // Check if target port is in pfwd_ports
302
+ if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
303
+ // Connect socket to that port
304
+ var chan = obj.net.createConnection({ host: obj.args.clientaddress, port: p_res.target_port }, function () {
305
+ //require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "CHANNEL_OPEN-open" });
306
+ // obj.downlinks[p_res.sender_chan].setEncoding('binary');//assume everything is binary, not interpreting
307
+ SendChannelOpenConfirm(socket.ws, p_res);
308
+ });
309
+
310
+ // Setup flow control
311
+ chan.maxInWindow = p_res.window_size; // Oddly, we are using the same window size as the other side.
312
+ chan.curInWindow = 0;
313
+
314
+ chan.on('data', function (ddata) {
315
+ // Relay data to fordwardclient
316
+ // TODO: Implement flow control
317
+ SendChannelData(socket.ws, p_res.sender_chan, ddata);
318
+ });
319
+
320
+ chan.on('error', function (e) {
321
+ Debug("Downlink connection error: " + e);
322
+ });
323
+
324
+ chan.on('end', function () {
325
+ var chan = obj.downlinks[p_res.sender_chan];
326
+ if (chan != null) {
327
+ Debug("Socket ends.");
328
+ try { SendChannelClose(socket.ws, p_res.sender_chan); } catch (ex) { }
329
+ delete obj.downlinks[p_res.sender_chan];
330
+ }
331
+ });
332
+
333
+ obj.downlinks[p_res.sender_chan] = chan;
334
+ } else {
335
+ // Not a supported port, fail the connection
336
+ SendChannelOpenFailure(socket.ws, p_res);
337
+ }
338
+ return p_res.len;
339
+ }
340
+ case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
341
+ Debug("APF: CHANNEL_OPEN_CONFIRMATION");
342
+ return 17;
343
+ }
344
+ case APFProtocol.CHANNEL_CLOSE: {
345
+ var rcpt_chan = ReadInt(data, 1);
346
+ Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
347
+ try { obj.downlinks[rcpt_chan].end(); } catch (ex) { }
348
+ return 5;
349
+ }
350
+ case APFProtocol.CHANNEL_DATA: {
351
+ Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
352
+ var rcpt_chan = ReadInt(data, 1);
353
+ var chan_data_len = ReadInt(data, 5);
354
+ var chan_data = data.substring(9, 9 + chan_data_len);
355
+ var chan = obj.downlinks[rcpt_chan];
356
+ if (chan != null) {
357
+ chan.curInWindow += chan_data_len;
358
+ try {
359
+ chan.write(Buffer.from(chan_data, 'binary'), function () {
360
+ Debug("Write completed.");
361
+ // If the incoming window is over half used, send an adjust.
362
+ if (this.curInWindow > (this.maxInWindow / 2)) { SendChannelWindowAdjust(socket.ws, rcpt_chan, this.curInWindow); this.curInWindow = 0; }
363
+ });
364
+ } catch (ex) { Debug("Cannot forward data to downlink socket."); }
365
+ }
366
+ return 9 + chan_data_len;
367
+ }
368
+ case APFProtocol.CHANNEL_WINDOW_ADJUST: {
369
+ Debug("APF: CHANNEL_WINDOW_ADJUST");
370
+ return 9;
371
+ }
372
+ case APFProtocol.JSON_CONTROL: {
373
+ Debug("APF: JSON_CONTROL");
374
+ var len = ReadInt(data, 1);
375
+ if (obj.onJsonControl) { var o = null; try { o = JSON.parse(data.substring(5, 5 + len)); } catch (ex) { } if (o != null) { obj.onJsonControl(o); } }
376
+ return 5 + len;
377
+ }
378
+ default: {
379
+ Debug("CMD: " + cmd + " is not implemented.");
380
+ obj.cirastate = CIRASTATE.FAILED;
381
+ return 0;
382
+ }
383
+ }
384
+ }
385
+
386
+ function parseChannelOpen(data) {
387
+ var result = { cmd: APFProtocol.CHANNEL_OPEN };
388
+ var chan_type_slen = ReadInt(data, 1);
389
+ result.chan_type = data.substring(5, 5 + chan_type_slen);
390
+ result.sender_chan = ReadInt(data, 5 + chan_type_slen);
391
+ result.window_size = ReadInt(data, 9 + chan_type_slen);
392
+ var c_len = ReadInt(data, 17 + chan_type_slen);
393
+ result.target_address = data.substring(21 + chan_type_slen, 21 + chan_type_slen + c_len);
394
+ result.target_port = ReadInt(data, 21 + chan_type_slen + c_len);
395
+ var o_len = ReadInt(data, 25 + chan_type_slen + c_len);
396
+ result.origin_address = data.substring(29 + chan_type_slen + c_len, 29 + chan_type_slen + c_len + o_len);
397
+ result.origin_port = ReadInt(data, 29 + chan_type_slen + c_len + o_len);
398
+ result.len = 33 + chan_type_slen + c_len + o_len;
399
+ return result;
400
+ }
401
+
402
+ function SendChannelOpenFailure(socket, chan_data) {
403
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan) + IntToStr(2) + IntToStr(0) + IntToStr(0));
404
+ Debug("APF: Send ChannelOpenFailure");
405
+ }
406
+
407
+ function SendChannelOpenConfirm(socket, chan_data) {
408
+ 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));
409
+ Debug("APF: Send ChannelOpenConfirmation");
410
+ }
411
+
412
+ function SendChannelWindowAdjust(socket, chan, size) {
413
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size));
414
+ Debug("APF: Send ChannelWindowAdjust, channel: " + chan + ", size: " + size);
415
+ }
416
+
417
+ function SendChannelData(socket, chan, data) {
418
+ socket.write(Buffer.concat([Buffer.from(String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(data.length), 'binary'), data]));
419
+ Debug("APF: Send ChannelData: " + data.toString('hex'));
420
+ }
421
+
422
+ function SendChannelClose(socket, chan) {
423
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan));
424
+ Debug("APF: Send ChannelClose ");
425
+ }
426
+
427
+ obj.connect = function () {
428
+ if (obj.forwardClient != null) {
429
+ try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); }
430
+ //obj.forwardClient = null;
431
+ }
432
+ obj.cirastate = CIRASTATE.INITIAL;
433
+ obj.pfwd_idx = 0;
434
+
435
+ //obj.forwardClient = new obj.ws(obj.args.mpsurl, obj.tlsoptions);
436
+ //obj.forwardClient.on("open", obj.onSecureConnect);
437
+
438
+ var wsoptions = obj.http.parseUri(obj.args.mpsurl);
439
+ wsoptions.rejectUnauthorized = 0;
440
+ obj.forwardClient = obj.http.request(wsoptions);
441
+ obj.forwardClient.upgrade = obj.onSecureConnect;
442
+ obj.forwardClient.end(); // end request, trigger completion of HTTP request
443
+ }
444
+
445
+ obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); } }
446
+
447
+ return obj;
448
+}
449
+
450
+module.exports = CreateAPFClient;
\ No newline at end of file
agents/modules_meshcore/apfclient.js
+52
-67
@@ -35,6 +35,9 @@ function CreateAPFClient(parent, args) {
35
obj.pfwd_idx = 0;
36
obj.timer = null; // Keep alive timer
37
38
+ // obj.onChannelClosed
39
+ // obj.onJsonControl
40
+
41
// Function copied from common.js
42
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.
43
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) {
142
}
143
144
obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
142
- //Debug("APF Secure WebSocket connected.");
145
+ Debug("APF Secure WebSocket connected.");
146
//console.log(JSON.stringify(resp));
147
obj.forwardClient.tag = { accumulator: [] };
148
obj.forwardClient.ws = ws;
149
obj.forwardClient.ws.on('end', function () {
147
- //Debug("APF: Connection is closing.");
148
- if (obj.timer != null) {
149
- clearInterval(obj.timer);
150
- obj.timer = null;
151
- }
150
+ Debug("APF: Connection is closing.");
151
+ if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
152
+ if (obj.onChannelClosed) { obj.onChannelClosed(obj); }
153
});
154
155
obj.forwardClient.ws.on('data', function (data) {
@@ -159,21 +160,16 @@ function CreateAPFClient(parent, args) {
160
len = ProcessData(obj.forwardClient);
161
if (len > 0) { obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len); }
162
if (obj.cirastate == CIRASTATE.FAILED) {
162
- //Debug("APF: in a failed state, destroying socket.");
163
+ Debug("APF: in a failed state, destroying socket.");
164
obj.forwardClient.ws.end();
165
}
166
} while (len > 0);
166
- } catch (e) {
167
- Debug(e);
168
- }
167
+ } catch (ex) { Debug(ex); }
168
});
169
170
obj.forwardClient.ws.on('error', function (e) {
172
- //Debug("APF: Connection error, ending connecting.");
173
- if (obj.timer != null) {
174
- clearInterval(obj.timer);
175
- obj.timer = null;
176
- }
171
+ Debug("APF: Connection error, ending connecting.");
172
+ if (obj.timer != null) { clearInterval(obj.timer); obj.timer = null; }
173
});
174
175
obj.state = CIRASTATE.INITIAL;
@@ -185,20 +181,20 @@ function CreateAPFClient(parent, args) {
181
function SendJsonControl(socket, o) {
182
var data = JSON.stringify(o)
183
socket.write(String.fromCharCode(APFProtocol.JSON_CONTROL) + IntToStr(data.length) + data);
188
- //Debug("APF: Send JSON control: " + data);
184
+ Debug("APF: Send JSON control: " + data);
185
}
186
187
function SendProtocolVersion(socket, uuid) {
188
var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(strToGuid(uuid)) + binzerostring(64);
189
socket.write(data);
194
- //Debug("APF: Send protocol version 1 0 " + uuid);
190
+ Debug("APF: Send protocol version 1 0 " + uuid);
191
obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
192
}
193
194
function SendServiceRequest(socket, service) {
195
var data = String.fromCharCode(APFProtocol.SERVICE_REQUEST) + IntToStr(service.length) + service;
196
socket.write(data);
201
- //Debug("APF: Send service request " + service);
197
+ Debug("APF: Send service request " + service);
198
if (service == 'auth@amt.intel.com') {
199
obj.cirastate = CIRASTATE.AUTH_SERVICE_REQUEST_SENT;
200
} else if (service == 'pfwd@amt.intel.com') {
@@ -213,7 +209,7 @@ function CreateAPFClient(parent, args) {
209
data += IntToStr(8) + 'password';
210
data += binzerostring(1) + IntToStr(pass.length) + pass;
211
socket.write(data);
216
- //Debug("APF: Send username password authentication to MPS");
212
+ Debug("APF: Send username password authentication to MPS");
213
obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
214
}
215
@@ -222,18 +218,18 @@ function CreateAPFClient(parent, args) {
218
var data = String.fromCharCode(APFProtocol.GLOBAL_REQUEST) + IntToStr(tcpipfwd.length) + tcpipfwd + binzerostring(1, 1);
219
data += IntToStr(amthostname.length) + amthostname + IntToStr(amtport);
220
socket.write(data);
225
- //Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
221
+ Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
222
obj.cirastate = CIRASTATE.GLOBAL_REQUEST_SENT;
223
}
224
225
function SendKeepAliveRequest(socket) {
226
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255));
231
- //Debug("APF: Send keepalive request");
227
+ Debug("APF: Send keepalive request");
228
}
229
230
function SendKeepAliveReply(socket, cookie) {
231
socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie));
236
- //Debug("APF: Send keepalive reply");
232
+ Debug("APF: Send keepalive reply");
233
}
234
235
function ProcessData(socket) {
@@ -246,7 +242,7 @@ function CreateAPFClient(parent, args) {
242
switch (cmd) {
243
case APFProtocol.SERVICE_ACCEPT: {
244
var slen = ReadInt(data, 1), service = data.substring(5, 6 + slen);
249
- //Debug("APF: Service request to " + service + " accepted.");
245
+ Debug("APF: Service request to " + service + " accepted.");
246
if (service == 'auth@amt.intel.com') {
247
if (obj.cirastate >= CIRASTATE.AUTH_SERVICE_REQUEST_SENT) {
248
SendUserAuthRequest(socket.ws, obj.args.mpsuser, obj.args.mpspass);
@@ -261,47 +257,47 @@ function CreateAPFClient(parent, args) {
257
case APFProtocol.REQUEST_SUCCESS: {
258
if (len >= 5) {
259
var port = ReadInt(data, 1);
264
- //Debug("APF: Request to port forward " + port + " successful.");
260
+ Debug("APF: Request to port forward " + port + " successful.");
261
// iterate to pending port forward request
262
if (obj.pfwd_idx < pfwd_ports.length) {
263
SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
264
} else {
265
// no more port forward, now setup timer to send keep alive
270
- //Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
266
+ Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
267
obj.timer = setInterval(function () {
268
SendKeepAliveRequest(obj.forwardClient.ws);
269
}, obj.args.mpskeepalive);//
270
}
271
return 5;
272
}
277
- //Debug("APF: Request successful.");
273
+ Debug("APF: Request successful.");
274
return 1;
275
}
276
case APFProtocol.USERAUTH_SUCCESS: {
281
- //Debug("APF: User Authentication successful");
277
+ Debug("APF: User Authentication successful");
278
// Send Pfwd service request
279
SendServiceRequest(socket.ws, 'pfwd@amt.intel.com');
280
return 1;
281
}
282
case APFProtocol.USERAUTH_FAILURE: {
287
- //Debug("APF: User Authentication failed");
283
+ Debug("APF: User Authentication failed");
284
obj.cirastate = CIRASTATE.FAILED;
285
return 14;
286
}
287
case APFProtocol.KEEPALIVE_REQUEST: {
292
- //Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
288
+ Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
289
SendKeepAliveReply(socket.ws, ReadInt(data, 1));
290
return 5;
291
}
292
case APFProtocol.KEEPALIVE_REPLY: {
297
- //Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
293
+ Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
294
return 5;
295
}
296
// Channel management
297
case APFProtocol.CHANNEL_OPEN: {
298
// Parse CHANNEL OPEN request
299
var p_res = parseChannelOpen(data);
304
- //Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
300
+ Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
301
// Check if target port is in pfwd_ports
302
if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
303
// Connect socket to that port
@@ -322,21 +318,15 @@ function CreateAPFClient(parent, args) {
318
});
319
320
chan.on('error', function (e) {
325
- //Debug("Downlink connection error: " + e);
321
+ Debug("Downlink connection error: " + e);
322
});
323
324
chan.on('end', function () {
325
var chan = obj.downlinks[p_res.sender_chan];
326
if (chan != null) {
331
- try {
332
- //Debug("Socket ends.");
333
- SendChannelClose(socket.ws, p_res.sender_chan);
334
- chan.xclosed = 1;
335
- // Add some delay before removing... otherwise race condition
336
- setTimeout(function () { delete obj.downlinks[p_res.sender_chan]; }, 100);
337
- } catch (e) {
338
- //Debug("Downlink connection exception: " + e);
339
- }
327
+ Debug("Socket ends.");
328
+ try { SendChannelClose(socket.ws, p_res.sender_chan); } catch (ex) { }
329
+ delete obj.downlinks[p_res.sender_chan];
330
}
331
});
332
@@ -348,22 +338,17 @@ function CreateAPFClient(parent, args) {
338
return p_res.len;
339
}
340
case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
351
- //Debug("APF: CHANNEL_OPEN_CONFIRMATION");
341
+ Debug("APF: CHANNEL_OPEN_CONFIRMATION");
342
return 17;
343
}
344
case APFProtocol.CHANNEL_CLOSE: {
345
var rcpt_chan = ReadInt(data, 1);
356
- //Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
357
- var chan = obj.downlinks[rcpt_chan];
358
- if ((chan != null) && (chan.xclosed !== 1)) {
359
- SendChannelClose(socket.ws, rcpt_chan);
360
- try { obj.downlinks[rcpt_chan].end(); } catch (e) { }
361
- delete obj.downlinks[rcpt_chan];
362
- }
346
+ Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
347
+ try { obj.downlinks[rcpt_chan].end(); } catch (ex) { }
348
return 5;
349
}
350
case APFProtocol.CHANNEL_DATA: {
366
- //Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
351
+ Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
352
var rcpt_chan = ReadInt(data, 1);
353
var chan_data_len = ReadInt(data, 5);
354
var chan_data = data.substring(9, 9 + chan_data_len);
@@ -372,22 +357,26 @@ function CreateAPFClient(parent, args) {
357
chan.curInWindow += chan_data_len;
358
try {
359
chan.write(Buffer.from(chan_data, 'binary'), function () {
375
- //Debug("Write completed.");
360
+ Debug("Write completed.");
361
// If the incoming window is over half used, send an adjust.
362
if (this.curInWindow > (this.maxInWindow / 2)) { SendChannelWindowAdjust(socket.ws, rcpt_chan, this.curInWindow); this.curInWindow = 0; }
363
});
379
- } catch (e) {
380
- //Debug("Cannot forward data to downlink socket.");
381
- }
364
+ } catch (ex) { Debug("Cannot forward data to downlink socket."); }
365
}
366
return 9 + chan_data_len;
367
}
368
case APFProtocol.CHANNEL_WINDOW_ADJUST: {
386
- //Debug("APF: CHANNEL_WINDOW_ADJUST ");
369
+ Debug("APF: CHANNEL_WINDOW_ADJUST");
370
return 9;
371
}
372
+ case APFProtocol.JSON_CONTROL: {
373
+ Debug("APF: JSON_CONTROL");
374
+ var len = ReadInt(data, 1);
375
+ if (obj.onJsonControl) { var o = null; try { o = JSON.parse(data.substring(5, 5 + len)); } catch (ex) { } if (o != null) { obj.onJsonControl(o); } }
376
+ return 5 + len;
377
+ }
378
default: {
390
- //Debug("CMD: " + cmd + " is not implemented.");
379
+ Debug("CMD: " + cmd + " is not implemented.");
380
obj.cirastate = CIRASTATE.FAILED;
381
return 0;
382
}
@@ -412,36 +401,32 @@ function CreateAPFClient(parent, args) {
401
402
function SendChannelOpenFailure(socket, chan_data) {
403
socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan) + IntToStr(2) + IntToStr(0) + IntToStr(0));
415
- //Debug("APF: Send ChannelOpenFailure");
404
+ Debug("APF: Send ChannelOpenFailure");
405
}
406
407
function SendChannelOpenConfirm(socket, chan_data) {
408
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));
420
- //Debug("APF: Send ChannelOpenConfirmation");
409
+ Debug("APF: Send ChannelOpenConfirmation");
410
}
411
412
function SendChannelWindowAdjust(socket, chan, size) {
413
socket.write(String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size));
425
- //Debug("APF: Send ChannelWindowAdjust: " + rstr2hex(data));
414
+ Debug("APF: Send ChannelWindowAdjust, channel: " + chan + ", size: " + size);
415
}
416
417
function SendChannelData(socket, chan, data) {
418
socket.write(Buffer.concat([Buffer.from(String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(data.length), 'binary'), data]));
430
- //Debug("APF: Send ChannelData: " + rstr2hex(buf));
419
+ Debug("APF: Send ChannelData: " + data.toString('hex'));
420
}
421
422
function SendChannelClose(socket, chan) {
423
socket.write(String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan));
435
- //Debug("APF: Send ChannelClose ");
424
+ Debug("APF: Send ChannelClose ");
425
}
426
427
obj.connect = function () {
428
if (obj.forwardClient != null) {
440
- try {
441
- obj.forwardClient.ws.end();
442
- } catch (e) {
443
- Debug(e);
444
- }
429
+ try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); }
430
//obj.forwardClient = null;
431
}
432
obj.cirastate = CIRASTATE.INITIAL;
@@ -457,7 +442,7 @@ function CreateAPFClient(parent, args) {
442
obj.forwardClient.end(); // end request, trigger completion of HTTP request
443
}
444
460
- obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (e) { Debug(e); } }
445
+ obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (ex) { Debug(ex); } }
446
447
return obj;
448
}
amt/amt-wsman-comm.js
+2
-4
@@ -240,19 +240,17 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
240
if (state == 2) {
241
// TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
242
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 };
243
- if (obj.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; }
243
+ if (obj.xtlsMethod == 1) { options.secureProtocol = 'TLSv1_method'; }
244
if (obj.xtlsoptions) {
245
if (obj.xtlsoptions.ca) options.ca = obj.xtlsoptions.ca;
246
if (obj.xtlsoptions.cert) options.cert = obj.xtlsoptions.cert;
247
if (obj.xtlsoptions.key) options.key = obj.xtlsoptions.key;
248
}
249
250
- //obj.socket = new TLSSocket(ser, options);
250
obj.socket = obj.tls.connect(obj.port, obj.host, options, obj.xxOnSocketConnected);
251
obj.socket.setEncoding('binary');
252
obj.socket.setTimeout(6000); // Set socket idle timeout
254
- obj.socket.on('error', function (err) { console.log("CIRA TLS Connection Error ", err); obj.xxOnSocketClosed(); });
255
- //obj.socket.on('error', function (e) { if (e.message && e.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } });
253
+ obj.socket.on('error', function (ex) { obj.xtlsMethod = 1 - obj.xtlsMethod; });
254
obj.socket.on('close', obj.xxOnSocketClosed);
255
obj.socket.on('timeout', obj.xxOnSocketTimeout);
256
amtmanager.js
+65
-33
@@ -76,6 +76,9 @@ module.exports.CreateAmtManager = function(parent) {
76
// Remove the device from the list
77
devices.splice(i, 1);
78
if (devices.length == 0) { delete obj.amtDevices[dev.nodeid]; } else { obj.amtDevices[dev.nodeid] = devices; }
79
+
80
+ // Notify connection closure if this is a LMS connection
81
+ if (dev.connType == 2) { dev.controlMsg({ action: "close" }); }
82
return true;
83
}
84
@@ -103,9 +106,13 @@ module.exports.CreateAmtManager = function(parent) {
106
var devices = obj.amtDevices[nodeid], dev = null;
107
if (devices != null) { for (var i in devices) { if ((devices[i].mpsConnection == connection) || (devices[i].host == connection)) { dev = devices[i]; } } }
108
if (dev != null) return false; // We are already managing this device on this connection
106
- dev = { nodeid: nodeid, connType: connType };
109
+ dev = { nodeid: nodeid, connType: connType, domainid: nodeid.split('/')[1] };
110
if (typeof connection == 'string') { dev.host = connection; }
111
if (typeof connection == 'object') { dev.mpsConnection = connection; }
112
+ dev.consoleMsg = function deviceConsoleMsg(msg) { if (typeof deviceConsoleMsg.conn == 'object') { deviceConsoleMsg.conn.ControlMsg({ action: 'console', msg: msg }); } }
113
+ dev.consoleMsg.conn = connection;
114
+ dev.controlMsg = function deviceControlMsg(msg) { if (typeof deviceControlMsg.conn == 'object') { deviceControlMsg.conn.ControlMsg(msg); } }
115
+ dev.controlMsg.conn = connection;
116
parent.debug('amt', "Start Management", nodeid, connType);
117
addAmtDevice(dev);
118
fetchIntelAmtInformation(dev);
@@ -192,6 +199,7 @@ module.exports.CreateAmtManager = function(parent) {
199
//if (node.host) { dev.host = node.host.toLowerCase(); }
200
dev.meshid = node.meshid;
201
dev.intelamt = node.intelamt;
202
+ dev.consoleMsg("Attempting Intel AMT connection...");
203
attemptInitialContact(dev);
204
});
205
}
@@ -201,7 +209,7 @@ module.exports.CreateAmtManager = function(parent) {
209
parent.debug('amt', "Attempt Initial Contact", dev.name, dev.connType);
210
211
if ((dev.acctry == null) && ((typeof dev.intelamt.user != 'string') || (typeof dev.intelamt.pass != 'string'))) {
204
- if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { return; }
212
+ if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { removeAmtDevice(dev); return; }
213
}
214
215
switch (dev.connType) {
@@ -315,6 +323,7 @@ module.exports.CreateAmtManager = function(parent) {
323
// Check the response
324
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)) {
325
// Everything looks good
326
+ dev.consoleMsg(stack.wsman.comm.xtls ? "Intel AMT connected with TLS." : "Intel AMT connected.");
327
dev.state = 1;
328
if (dev.aquired == null) { dev.aquired = {}; }
329
dev.aquired.controlMode = responses['IPS_HostBasedSetupService'].response.CurrentControlMode; // 1 = CCM, 2 = ACM
@@ -330,15 +339,20 @@ module.exports.CreateAmtManager = function(parent) {
339
340
// Perform Intel AMT clock sync
341
attemptSyncClock(dev, function () {
333
- attemptFetchHardwareInventory(dev); // See if we need to get hardware inventory
334
-
335
- if (dev.connType != 2) {
336
- // Start power polling if not connected to LMS
337
- var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); }
338
- ppfunc.dev = dev;
339
- dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds.
340
- fetchPowerState(dev);
341
- }
342
+ // See if we need to get hardware inventory
343
+ attemptFetchHardwareInventory(dev, function () {
344
+ dev.consoleMsg('Done.');
345
+ if (dev.connType != 2) {
346
+ // Start power polling if not connected to LMS
347
+ var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); }
348
+ ppfunc.dev = dev;
349
+ dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds.
350
+ fetchPowerState(dev);
351
+ } else {
352
+ // For LMS connections, close now.
353
+ dev.controlMsg({ action: "close" });
354
+ }
355
+ });
356
});
357
} else {
358
// We got a bad response
@@ -509,7 +523,8 @@ module.exports.CreateAmtManager = function(parent) {
523
// Care should be take not to have many pending WSMAN called when performing clock sync.
524
function attemptSyncClock(dev, func) {
525
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
512
- dev.clockSyncCompleted = func;
526
+ dev.taskCount = 1;
527
+ dev.taskCompleted = func;
528
dev.amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(attemptSyncClockEx);
529
}
530
@@ -517,17 +532,19 @@ module.exports.CreateAmtManager = function(parent) {
532
function attemptSyncClockEx(stack, name, response, status) {
533
const dev = stack.dev;
534
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
520
- if (status != 200) { removeDevice(dev.nodeid); }
535
+ if (status != 200) { removeDevice(dev.nodeid); return; }
536
537
// Compute how much drift between Intel AMT and our clock.
538
var t = new Date(), now = new Date();
539
t.setTime(response.Body['Ta0'] * 1000);
540
if (Math.abs(t - now) > 10000) { // If the Intel AMT clock is more than 10 seconds off, set it.
541
+ dev.consoleMsg("Performing clock sync.");
542
var Tm1 = Math.round(now.getTime() / 1000);
543
dev.amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, attemptSyncClockSet);
544
} else {
545
// Clock is fine, we are done.
530
- if (dev.clockSyncCompleted != null) { var f = dev.clockSyncCompleted; delete dev.clockSyncCompleted; f(); }
546
+ dev.consoleMsg("Clock ok.");
547
+ devTaskCompleted(dev)
548
}
549
}
550
@@ -536,28 +553,37 @@ module.exports.CreateAmtManager = function(parent) {
553
const dev = stack.dev;
554
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
555
if (status != 200) { removeDevice(dev.nodeid); }
539
- if (dev.clockSyncCompleted != null) { var f = dev.clockSyncCompleted; delete dev.clockSyncCompleted; f(); }
556
+ devTaskCompleted(dev)
557
}
558
542
- function attemptFetchHardwareInventory(dev) {
543
- if (obj.amtDevices[dev.nodeid] == null) return false; // Device no longer exists, ignore this request.
559
+ function attemptFetchHardwareInventory(dev, func) {
560
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
561
const mesh = parent.webserver.meshes[dev.meshid];
545
- if (mesh == null) { removeDevice(dev.nodeid); return false; }
562
+ if (mesh == null) { removeDevice(dev.nodeid); return; }
563
if (mesh.mtype == 1) { // If this is a Intel AMT only device group, pull the hardware inventory and network information for this device
564
+ dev.consoleMsg("Fetching hardware inventory.");
565
+ dev.taskCount = 2;
566
+ dev.taskCompleted = func;
567
dev.amtstack.BatchEnum('', ['*CIM_ComputerSystemPackage', 'CIM_SystemPackaging', '*CIM_Chassis', 'CIM_Chip', '*CIM_Card', '*CIM_BIOSElement', 'CIM_Processor', 'CIM_PhysicalMemory', 'CIM_MediaAccessDevice', 'CIM_PhysicalPackage'], attemptFetchHardwareInventoryResponse);
568
dev.amtstack.BatchEnum('', ['AMT_EthernetPortSettings'], attemptFetchNetworkResponse);
549
- return true;
569
+ } else {
570
+ if (func) { func(); }
571
}
551
- return false;
572
+ }
573
+
574
+ //
575
+ function devTaskCompleted(dev) {
576
+ dev.taskCount--;
577
+ if (dev.taskCount == 0) { var f = dev.taskCompleted; delete dev.taskCount; delete dev.taskCompleted; if (f != null) { f(); } }
578
}
579
580
function attemptFetchNetworkResponse(stack, name, responses, status) {
581
const dev = stack.dev;
582
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
557
- if (status != 200) return;
583
+ if (status != 200) { devTaskCompleted(dev); return; }
584
585
//console.log(JSON.stringify(responses, null, 2));
560
- if ((responses['AMT_EthernetPortSettings'] == null) || (responses['AMT_EthernetPortSettings'].responses == null)) return;
586
+ if ((responses['AMT_EthernetPortSettings'] == null) || (responses['AMT_EthernetPortSettings'].responses == null)) { devTaskCompleted(dev); return; }
587
588
// Find the wired and wireless interfaces
589
var wired = null, wireless = null;
@@ -567,7 +593,7 @@ module.exports.CreateAmtManager = function(parent) {
593
if (netif.WLANLinkProtectionLevel != null) { wireless = netif; } else { wired = netif; }
594
}
595
}
570
- if ((wired == null) && (wireless == null)) return;
596
+ if ((wired == null) && (wireless == null)) { devTaskCompleted(dev); return; }
597
598
// Sent by the agent to update agent network interface information
599
var net = { netif2: {} };
@@ -601,6 +627,8 @@ module.exports.CreateAmtManager = function(parent) {
627
628
// Event the node interface information change
629
parent.DispatchEvent(parent.webserver.CreateMeshDispatchTargets(dev.meshid, [dev.nodeid]), obj, { action: 'ifchange', nodeid: dev.nodeid, domain: dev.nodeid.split('/')[1], nolog: 1 });
630
+
631
+ devTaskCompleted(dev);
632
}
633
634
@@ -625,7 +653,7 @@ module.exports.CreateAmtManager = function(parent) {
653
function attemptFetchHardwareInventoryResponse(stack, name, responses, status) {
654
const dev = stack.dev;
655
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
628
- if (status != 200) return;
656
+ if (status != 200) { devTaskCompleted(dev); return; }
657
658
// Extract basic data
659
var hw = {}
@@ -648,9 +676,11 @@ module.exports.CreateAmtManager = function(parent) {
676
var m2 = {}, m = hw.PhysicalMemory[i];
677
m2.BankLabel = m.BankLabel;
678
m2.Capacity = m.Capacity;
651
- m2.PartNumber = m.PartNumber.trim();
652
- m2.SerialNumber = m.SerialNumber.trim();
653
- m2.Manufacturer = m.Manufacturer.trim();
679
+ if (m.PartNumber) { m2.PartNumber = m.PartNumber.trim(); }
680
+ if (typeof m.SerialNumber == 'string') { m2.SerialNumber = m.SerialNumber.trim(); }
681
+ if (typeof m.SerialNumber == 'number') { m2.SerialNumber = m.SerialNumber; }
682
+ if (typeof m.SerialNumber == 'string') { m2.Manufacturer = m.Manufacturer.trim(); }
683
+ if (typeof m.Manufacturer == 'number') { m2.Manufacturer = m.Manufacturer; }
684
memory.push(m2);
685
}
686
hw2.hardware.windows.memory = memory;
@@ -660,21 +690,21 @@ module.exports.CreateAmtManager = function(parent) {
690
for (var i in hw.MediaAccessDevice) {
691
var m2 = {}, m = hw.MediaAccessDevice[i];
692
m2.Caption = m.DeviceID;
663
- m2.Size = (m.MaxMediaSize * 1000);
693
+ if (m.MaxMediaSize) { m2.Size = (m.MaxMediaSize * 1000); }
694
drives.push(m2);
695
}
696
hw2.hardware.identifiers.storage_devices = drives;
697
}
698
if (hw.Bios != null) {
669
- hw2.hardware.identifiers.bios_vendor = hw.Bios.Manufacturer.trim();
699
+ if (hw.Bios.Manufacturer) { hw2.hardware.identifiers.bios_vendor = hw.Bios.Manufacturer.trim(); }
700
hw2.hardware.identifiers.bios_version = hw.Bios.Version;
701
if (hw.Bios.ReleaseDate && hw.Bios.ReleaseDate.Datetime) { hw2.hardware.identifiers.bios_date = hw.Bios.ReleaseDate.Datetime; }
702
}
703
if (hw.PhysicalPackage != null) {
674
- hw2.hardware.identifiers.board_name = hw.Card.Model.trim();
675
- hw2.hardware.identifiers.board_vendor = hw.Card.Manufacturer.trim();
676
- hw2.hardware.identifiers.board_version = hw.Card.Version.trim();
677
- hw2.hardware.identifiers.board_serial = hw.Card.SerialNumber.trim();
704
+ if (hw.Card.Model) { hw2.hardware.identifiers.board_name = hw.Card.Model.trim(); }
705
+ if (hw.Card.Manufacturer) { hw2.hardware.identifiers.board_vendor = hw.Card.Manufacturer.trim(); }
706
+ if (hw.Card.Version) { hw2.hardware.identifiers.board_version = hw.Card.Version.trim(); }
707
+ if (hw.Card.SerialNumber) { hw2.hardware.identifiers.board_serial = hw.Card.SerialNumber.trim(); }
708
}
709
if ((hw.Chips != null) && (hw.Chips.length > 0)) {
710
for (var i in hw.Chips) {
@@ -704,6 +734,8 @@ module.exports.CreateAmtManager = function(parent) {
734
parent.DispatchEvent(parent.webserver.CreateMeshDispatchTargets(dev.meshid, [dev.nodeid]), obj, event);
735
}
736
});
737
+
738
+ devTaskCompleted(dev);
739
}
740
741
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); }
mpsserver.js
+10
@@ -285,6 +285,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
285
socket.SetupChannel.parent = obj;
286
socket.SetupChannel.conn = socket;
287
socket.websocket = 1;
288
+ socket.ControlMsg = function ControlMsg(message) { return ControlMsg.parent.SendJsonControl(ControlMsg.conn, message); }
289
+ socket.ControlMsg.parent = obj;
290
+ socket.ControlMsg.conn = socket;
291
parent.debug('mps', "New CIRA websocket connection");
292
293
socket.on('message', function (data) {
@@ -913,6 +916,13 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
916
for (var i in connections) { obj.close(connections[i]); }
917
};
918
919
+ obj.SendJsonControl = function(socket, data) {
920
+ if (socket.tag.connType == 0) return; // This command is valid only for connections that are not really CIRA.
921
+ parent.debug('mpscmd', '<-- JSON_CONTROL');
922
+ if (typeof data == 'object') { data = JSON.stringify(data); }
923
+ Write(socket, String.fromCharCode(APFProtocol.JSON_CONTROL) + common.IntToStr(data.length) + data);
924
+ }
925
+
926
function SendServiceAccept(socket, service) {
927
parent.debug('mpscmd', '<-- SERVICE_ACCEPT', service);
928
Write(socket, String.fromCharCode(APFProtocol.SERVICE_ACCEPT) + common.IntToStr(service.length) + service);
webserver.js
+3
-1
@@ -3520,6 +3520,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3520
if (ws.logfile != null) { recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, ws) { obj.fs.close(fd); delete ws.logfile; }, ws); }
3521
});
3522
3523
+ // 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
3524
+
3525
// Fetch Intel AMT credentials & Setup interceptor
3526
if (req.query.p == 1) {
3527
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) {
3589
// Compute target port
3590
var port = 16992;
3591
if (node.intelamt.tls > 0) port = 16993; // This is a direct connection, use TLS when possible
3590
- if (req.query.p == 2) port += 2;
3592
+ if ((req.query.p == 2) || (req.query.p == 4)) port += 2;
3593
3594
if (node.intelamt.tls == 0) {
3595
// If this is TCP (without TLS) set a normal TCP socket