Merged APF and MPS servers, improved APF client.
Ylian Saint-Hilaire committed
Oct 8, 2020 at 19:47 UTC
bc4e07b5fe84c4480b7c809a82815cd37595dbeb
8 files changed
+499
-1246
agents/modules_meshcore/apfclient.js
+71
-117
@@ -6,60 +6,30 @@
6
* @version v0.0.1
7
*/
8
9
-function CreateAPFClient(parent, args) {
9
+function CreateAPFClient(parent, args) {
10
var obj = {};
11
obj.parent = parent;
12
obj.args = args;
13
obj.http = require('http');
14
- //obj.common = require('common');
15
- obj.net = require('net');
14
+ obj.net = require('net');
15
obj.forwardClient = null;
16
obj.downlinks = {};
17
obj.pfwd_idx = 0;
19
- // keep alive timer
20
- obj.timer = null;
21
-
22
- // some function copied from common.js
23
- function ReadInt(v, p) {
24
- return (v.charCodeAt(p) * 0x1000000) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3);
25
- }; // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
26
-
27
- function IntToStr(v) {
28
- return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
29
- };
30
-
31
- function hex2rstr(d) {
32
- var r = '', m = ('' + d).match(/../g), t;
33
- while (t = m.shift()) { r += String.fromCharCode('0x' + t); }
34
- return r;
35
- };
36
-
37
- // Convert decimal to hex
38
- function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); };
39
-
40
- // Convert a raw string to a hex string
41
- function rstr2hex(input) {
42
- var r = '', i;
43
- for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); }
44
- return r;
45
- };
46
-
47
- function d2h(d) {
48
- return (d / 256 + 1 / 512).toString(16).substring(2, 4);
49
- }
50
-
51
- function buf2hex(input) {
52
- var r = '', i;
53
- for (i = 0; i < input.length; i++) { r += d2h(input[i]); }
54
- return r;
55
- };
18
+ obj.timer = null; // Keep alive timer
19
+
20
+ // Function copied from common.js
21
+ 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.
22
+ function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); };
23
+ function hex2rstr(d) { var r = '', m = ('' + d).match(/../g), t; while (t = m.shift()) { r += String.fromCharCode('0x' + t); } return r; };
24
+ function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }; // Convert decimal to hex
25
+ 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
26
+ function d2h(d) { return (d / 256 + 1 / 512).toString(16).substring(2, 4); }
27
+ function buf2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += d2h(input[i]); } return r; };
28
+ function Debug(str) { if (obj.parent.debug) { console.log(str); } }
29
+ 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); }
30
+ 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; }
31
+ function binzerostring(len) { var res = ''; for (var l = 0; l < len; l++) { res += String.fromCharCode(0 & 0xFF); } return res; }
32
57
-
58
- function Debug(str) {
59
- if (obj.parent.debug) {
60
- console.log(str);
61
- }
62
- }
33
// CIRA state
34
var CIRASTATE = {
35
INITIAL: 0,
@@ -85,9 +55,10 @@ function CreateAPFClient(parent, args) {
55
obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
56
obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
57
58
+ // Intel AMT forwarded port list for non-TLS mode
59
+ //var pfwd_ports = [16992, 623, 16994, 5900];
60
+ var pfwd_ports = [ 16992 ];
61
89
- // AMT forwarded port list for non-TLS mode
90
- var pfwd_ports = [16992, 623, 16994, 5900];
62
// protocol definitions
63
var APFProtocol = {
64
UNKNOWN: 0,
@@ -152,7 +123,7 @@ function CreateAPFClient(parent, args) {
123
Debug("APF Secure WebSocket connected.");
124
//console.log(JSON.stringify(resp));
125
obj.forwardClient.tag = { accumulator: [] };
155
- obj.forwardClient.ws = ws;
126
+ obj.forwardClient.ws = ws;
127
obj.forwardClient.ws.on('end', function () {
128
Debug("APF: Connection is closing.");
129
if (obj.timer != null) {
@@ -162,12 +133,12 @@ function CreateAPFClient(parent, args) {
133
});
134
135
obj.forwardClient.ws.on('data', function (data) {
165
- obj.forwardClient.tag.accumulator += hex2rstr(buf2hex(data));
136
+ obj.forwardClient.tag.accumulator += hex2rstr(buf2hex(data));
137
try {
138
var len = 0;
139
do {
140
len = ProcessData(obj.forwardClient);
170
- if (len > 0) {
141
+ if (len > 0) {
142
obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len);
143
}
144
if (obj.cirastate == CIRASTATE.FAILED) {
@@ -178,44 +149,26 @@ function CreateAPFClient(parent, args) {
149
} catch (e) {
150
Debug(e);
151
}
181
- });
182
-
152
+ });
153
+
154
obj.forwardClient.ws.on('error', function (e) {
155
Debug("APF: Connection error, ending connecting.");
156
if (obj.timer != null) {
157
clearInterval(obj.timer);
158
obj.timer = null;
159
}
189
- });
160
+ });
161
162
obj.state = CIRASTATE.INITIAL;
163
SendProtocolVersion(obj.forwardClient.ws, obj.args.clientuuid);
164
SendServiceRequest(obj.forwardClient.ws, 'auth@amt.intel.com');
165
}
166
196
- 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); }
197
- function strToGuid(s) {
198
- s = s.replace(/-/g, '');
199
- var ret = s.substring(6, 8) + s.substring(4, 6) + s.substring(2, 4) + s.substring(0, 2);
200
- ret += s.substring(10, 12) + s.substring(8, 10) + s.substring(14, 16) + s.substring(12, 14) + s.substring(16, 20) + s.substring(20);
201
- return ret;
202
- }
203
-
204
- function binzerostring(len) {
205
- var res='';
206
- for (var l=0; l< len ; l++) {
207
- res+=String.fromCharCode(0 & 0xFF);
208
- }
209
- return res;
210
- }
211
-
212
-
213
-
214
- function SendProtocolVersion(socket, uuid) {
167
+ function SendProtocolVersion(socket, uuid) {
168
var buuid = strToGuid(uuid);
169
var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + '' + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(buuid) + binzerostring(64);
217
- socket.write(data);
218
- Debug("APF: Send protocol version 1 0 " + uuid);
170
+ socket.write(data);
171
+ Debug("APF: Send protocol version 1 0 " + uuid);
172
obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
173
}
174
@@ -267,7 +220,8 @@ function CreateAPFClient(parent, args) {
220
var len = socket.tag.accumulator.length;
221
var data = socket.tag.accumulator;
222
if (len == 0) { return 0; }
270
- // respond to MPS according to obj.cirastate
223
+
224
+ // Respond to MPS according to obj.cirastate
225
switch (cmd) {
226
case APFProtocol.SERVICE_ACCEPT: {
227
var slen = ReadInt(data, 1);
@@ -325,39 +279,50 @@ function CreateAPFClient(parent, args) {
279
}
280
// Channel management
281
case APFProtocol.CHANNEL_OPEN: {
328
- //parse CHANNEL OPEN request
282
+ // Parse CHANNEL OPEN request
283
var p_res = parseChannelOpen(data);
284
Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
285
// Check if target port is in pfwd_ports
286
if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
333
- // connect socket to that port
334
- obj.downlinks[p_res.sender_chan] = obj.net.createConnection({ host: obj.args.clientaddress, port: p_res.target_port }, function () {
335
- //obj.downlinks[p_res.sender_chan].setEncoding('binary');//assume everything is binary, not interpreting
287
+ // Connect socket to that port
288
+ var chan = obj.net.createConnection({ host: obj.args.clientaddress, port: p_res.target_port }, function () {
289
+ //require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "CHANNEL_OPEN-open" });
290
+ // obj.downlinks[p_res.sender_chan].setEncoding('binary');//assume everything is binary, not interpreting
291
SendChannelOpenConfirm(socket.ws, p_res);
292
});
293
339
- obj.downlinks[p_res.sender_chan].on('data', function (ddata) {
340
- //Relay data to fordwardclient
294
+ // Setup flow control
295
+ chan.maxInWindow = p_res.window_size; // Oddly, we are using the same window size as the other side.
296
+ chan.curInWindow = 0;
297
+
298
+ chan.on('data', function (ddata) {
299
+ // Relay data to fordwardclient
300
+ // TODO: Implement flow control
301
SendChannelData(socket.ws, p_res.sender_chan, ddata.length, ddata);
302
});
303
344
- obj.downlinks[p_res.sender_chan].on('error', function (e) {
304
+ chan.on('error', function (e) {
305
Debug("Downlink connection error: " + e);
306
});
307
348
- obj.downlinks[p_res.sender_chan].on('end', function () {
349
- if (obj.downlinks[p_res.sender_chan]) {
308
+ chan.on('end', function () {
309
+ var chan = obj.downlinks[p_res.sender_chan];
310
+ if (chan != null) {
311
try {
312
Debug("Socket ends.");
313
SendChannelClose(socket.ws, p_res.sender_chan);
353
- // add some delay before removing... otherwise race condition
354
- setTimeout(function () { delete obj.downlinks[p_res.sender_chan];},100);
314
+ chan.xclosed = 1;
315
+ // Add some delay before removing... otherwise race condition
316
+ setTimeout(function () { delete obj.downlinks[p_res.sender_chan]; }, 100);
317
} catch (e) {
318
Debug("Downlink connection exception: " + e);
319
}
320
}
321
});
322
+
323
+ obj.downlinks[p_res.sender_chan] = chan;
324
} else {
325
+ // Not a supported port, fail the connection
326
SendChannelOpenFailure(socket.ws, p_res);
327
}
328
return p_res.len;
@@ -369,11 +334,12 @@ function CreateAPFClient(parent, args) {
334
case APFProtocol.CHANNEL_CLOSE: {
335
var rcpt_chan = ReadInt(data, 1);
336
Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
372
- SendChannelClose(socket.ws, rcpt_chan);
373
- try {
374
- obj.downlinks[rcpt_chan].end();
337
+ var chan = obj.downlinks[rcpt_chan];
338
+ if ((chan != null) && (chan.xclosed !== 1)) {
339
+ SendChannelClose(socket.ws, rcpt_chan);
340
+ try { obj.downlinks[rcpt_chan].end(); } catch (e) { }
341
delete obj.downlinks[rcpt_chan];
376
- } catch (e) { }
342
+ }
343
return 5;
344
}
345
case APFProtocol.CHANNEL_DATA: {
@@ -381,11 +347,14 @@ function CreateAPFClient(parent, args) {
347
var rcpt_chan = ReadInt(data, 1);
348
var chan_data_len = ReadInt(data, 5);
349
var chan_data = data.substring(9, 9 + chan_data_len);
384
- if (obj.downlinks[rcpt_chan]) {
350
+ var chan = obj.downlinks[rcpt_chan];
351
+ if (chan != null) {
352
+ chan.curInWindow += chan_data_len;
353
try {
386
- obj.downlinks[rcpt_chan].write(chan_data, 'binary', function () {
354
+ chan.write(chan_data, 'binary', function () {
355
Debug("Write completed.");
388
- SendChannelWindowAdjust(socket.ws, rcpt_chan, chan_data_len);//I have full window capacity now
356
+ // If the incoming window is over half used, send an adjust.
357
+ if (this.curInWindow > (this.maxInWindow / 2)) { SendChannelWindowAdjust(socket.ws, rcpt_chan, this.curInWindow); this.curInWindow = 0; }
358
});
359
} catch (e) {
360
Debug("Cannot forward data to downlink socket.");
@@ -406,17 +375,7 @@ function CreateAPFClient(parent, args) {
375
}
376
377
function parseChannelOpen(data) {
409
- var result = {
410
- len: 0, //to be filled later
411
- cmd: APFProtocol.CHANNEL_OPEN,
412
- chan_type: "", //to be filled later
413
- sender_chan: 0, //to be filled later
414
- window_size: 0, //to be filled later
415
- target_address: "", //to be filled later
416
- target_port: 0, //to be filled later
417
- origin_address: "", //to be filled later
418
- origin_port: 0, //to be filled later
419
- };
378
+ var result = { cmd: APFProtocol.CHANNEL_OPEN };
379
var chan_type_slen = ReadInt(data, 1);
380
result.chan_type = data.substring(5, 5 + chan_type_slen);
381
result.sender_chan = ReadInt(data, 5 + chan_type_slen);
@@ -430,12 +389,14 @@ function CreateAPFClient(parent, args) {
389
result.len = 33 + chan_type_slen + c_len + o_len;
390
return result;
391
}
392
+
393
function SendChannelOpenFailure(socket, chan_data) {
394
var data = String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan)
395
+ IntToStr(2) + IntToStr(0) + IntToStr(0);
396
socket.write(data);
397
Debug("APF: Send ChannelOpenFailure");
398
}
399
+
400
function SendChannelOpenConfirm(socket, chan_data) {
401
var data = String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + IntToStr(chan_data.sender_chan)
402
+ IntToStr(chan_data.sender_chan) + IntToStr(chan_data.window_size) + IntToStr(0xFFFFFFFF);
@@ -472,25 +433,18 @@ function CreateAPFClient(parent, args) {
433
}
434
obj.cirastate = CIRASTATE.INITIAL;
435
obj.pfwd_idx = 0;
475
-
436
+
437
//obj.forwardClient = new obj.ws(obj.args.mpsurl, obj.tlsoptions);
438
//obj.forwardClient.on("open", obj.onSecureConnect);
439
479
-
480
- var wsoptions = obj.http.parseUri(obj.args.mpsurl);
440
+ var wsoptions = obj.http.parseUri(obj.args.mpsurl);
441
wsoptions.rejectUnauthorized = 0;
482
- obj.forwardClient = obj.http.request(wsoptions);
483
- obj.forwardClient.upgrade = obj.onSecureConnect;
442
+ obj.forwardClient = obj.http.request(wsoptions);
443
+ obj.forwardClient.upgrade = obj.onSecureConnect;
444
obj.forwardClient.end(); // end request, trigger completion of HTTP request
445
}
446
487
- obj.disconnect = function () {
488
- try {
489
- obj.forwardClient.ws.end();
490
- } catch (e) {
491
- Debug(e);
492
- }
493
- }
447
+ obj.disconnect = function () { try { obj.forwardClient.ws.end(); } catch (e) { Debug(e); } }
448
449
return obj;
450
}
amtmanager.js
+2
-2
@@ -44,7 +44,7 @@ module.exports.CreateAmtManager = function(parent) {
44
// React to nodes connecting and disconnecting
45
if (event.action == 'nodeconnect') {
46
if ((event.conn & 14) != 0) { // connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 4 = Intel AMT local, 8 = Intel AMT Relay, 16 = MQTT
47
- //if ((event.conn & 2) == 0) return // Debug: Only look at CIRA connections *****************************
47
+ //if ((event.conn & 2) == 0) return // Debug: Only look at CIRA connections
48
49
// We have an OOB connection to Intel AMT, update our information
50
var dev = obj.amtDevices[event.nodeid];
@@ -266,7 +266,7 @@ module.exports.CreateAmtManager = function(parent) {
266
}
267
268
function attemptLocalConnectResponse(stack, name, responses, status) {
269
- //console.log('attemptLocalConnectResponse', status);
269
+ //console.log('attemptLocalConnectResponse', status, stack.dev.name);
270
271
// Release active connection to this host.
272
delete obj.activeLocalConnections[stack.wsman.comm.host];
apfserver.js
deleted
-734
@@ -1,734 +0,0 @@
1
-/**
2
-* @description MeshCentral Intel(R) AMT APF over websocket server
3
-* @author Ylian Saint-Hilaire/Joko Sastriawan
4
-* @copyright Intel Corporation 2018-2020
5
-* @license Apache-2.0
6
-* @version v0.0.1
7
-*/
8
-
9
-/*jslint node: true */
10
-/*jshint node: true */
11
-/*jshint strict:false */
12
-/*jshint -W097 */
13
-/*jshint esversion: 6 */
14
-"use strict";
15
-
16
-// Construct a Intel AMT APF server object
17
-module.exports.CreateApfServer = function (parent, db, args) {
18
- var obj = {};
19
- obj.parent = parent;
20
- obj.db = db;
21
- obj.args = args;
22
- obj.apfConnections = {};
23
- const constants = (require('crypto').constants ? require('crypto').constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead.
24
- const common = require("./common.js");
25
- const net = require("net");
26
- const MAX_IDLE = 90000; // 90 seconds max idle time, higher than the typical KEEP-ALIVE periode of 60 seconds
27
-
28
-
29
- const APFProtocol = {
30
- UNKNOWN: 0,
31
- DISCONNECT: 1,
32
- SERVICE_REQUEST: 5,
33
- SERVICE_ACCEPT: 6,
34
- USERAUTH_REQUEST: 50,
35
- USERAUTH_FAILURE: 51,
36
- USERAUTH_SUCCESS: 52,
37
- GLOBAL_REQUEST: 80,
38
- REQUEST_SUCCESS: 81,
39
- REQUEST_FAILURE: 82,
40
- CHANNEL_OPEN: 90,
41
- CHANNEL_OPEN_CONFIRMATION: 91,
42
- CHANNEL_OPEN_FAILURE: 92,
43
- CHANNEL_WINDOW_ADJUST: 93,
44
- CHANNEL_DATA: 94,
45
- CHANNEL_CLOSE: 97,
46
- PROTOCOLVERSION: 192,
47
- KEEPALIVE_REQUEST: 208,
48
- KEEPALIVE_REPLY: 209,
49
- KEEPALIVE_OPTIONS_REQUEST: 210,
50
- KEEPALIVE_OPTIONS_REPLY: 211
51
- };
52
-
53
- /*
54
- const APFDisconnectCode = {
55
- HOST_NOT_ALLOWED_TO_CONNECT: 1,
56
- PROTOCOL_ERROR: 2,
57
- KEY_EXCHANGE_FAILED: 3,
58
- RESERVED: 4,
59
- MAC_ERROR: 5,
60
- COMPRESSION_ERROR: 6,
61
- SERVICE_NOT_AVAILABLE: 7,
62
- PROTOCOL_VERSION_NOT_SUPPORTED: 8,
63
- HOST_KEY_NOT_VERIFIABLE: 9,
64
- CONNECTION_LOST: 10,
65
- BY_APPLICATION: 11,
66
- TOO_MANY_CONNECTIONS: 12,
67
- AUTH_CANCELLED_BY_USER: 13,
68
- NO_MORE_AUTH_METHODS_AVAILABLE: 14,
69
- INVALID_CREDENTIALS: 15,
70
- CONNECTION_TIMED_OUT: 16,
71
- BY_POLICY: 17,
72
- TEMPORARILY_UNAVAILABLE: 18
73
- };
74
-
75
- const APFChannelOpenFailCodes = {
76
- ADMINISTRATIVELY_PROHIBITED: 1,
77
- CONNECT_FAILED: 2,
78
- UNKNOWN_CHANNEL_TYPE: 3,
79
- RESOURCE_SHORTAGE: 4,
80
- };
81
- */
82
-
83
- const APFChannelOpenFailureReasonCode = {
84
- AdministrativelyProhibited: 1,
85
- ConnectFailed: 2,
86
- UnknownChannelType: 3,
87
- ResourceShortage: 4,
88
- };
89
-
90
- // Stat counters
91
- var connectionCount = 0;
92
- var userAuthRequestCount = 0;
93
- var incorrectPasswordCount = 0;
94
- var meshNotFoundCount = 0;
95
- var unknownNodeCount = 0;
96
- var unknownMeshIdCount = 0;
97
- var addedDeviceCount = 0;
98
- var ciraTimeoutCount = 0;
99
- var protocolVersionCount = 0;
100
- var badUserNameLengthCount = 0;
101
- var channelOpenCount = 0;
102
- var channelOpenConfirmCount = 0;
103
- var channelOpenFailCount = 0;
104
- var channelCloseCount = 0;
105
- var disconnectCommandCount = 0;
106
- var socketClosedCount = 0;
107
- var socketErrorCount = 0;
108
- var maxDomainDevicesReached = 0;
109
-
110
- // Return statistics about this APF server
111
- obj.getStats = function () {
112
- return {
113
- apfConnections: Object.keys(obj.apfConnections).length,
114
- connectionCount: connectionCount,
115
- userAuthRequestCount: userAuthRequestCount,
116
- incorrectPasswordCount: incorrectPasswordCount,
117
- meshNotFoundCount: meshNotFoundCount,
118
- unknownNodeCount: unknownNodeCount,
119
- unknownMeshIdCount: unknownMeshIdCount,
120
- addedDeviceCount: addedDeviceCount,
121
- apfTimeoutCount: ciraTimeoutCount,
122
- protocolVersionCount: protocolVersionCount,
123
- badUserNameLengthCount: badUserNameLengthCount,
124
- channelOpenCount: channelOpenCount,
125
- channelOpenConfirmCount: channelOpenConfirmCount,
126
- channelOpenFailCount: channelOpenFailCount,
127
- channelCloseCount: channelCloseCount,
128
- disconnectCommandCount: disconnectCommandCount,
129
- socketClosedCount: socketClosedCount,
130
- socketErrorCount: socketErrorCount,
131
- maxDomainDevicesReached : maxDomainDevicesReached
132
- };
133
- }
134
-
135
- obj.onConnection = function(socket) {
136
- connectionCount++;
137
- // treat APS over WS like tlsoffload APF
138
- socket.tag = { first: true, clientCert: null, accumulator: "", activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
139
- parent.debug('apf', "New APF connection");
140
- parent.debug('apf',"WS Extensions:"+socket.extensions);
141
- parent.debug('apf',"WS Binary type:"+socket.binaryType);
142
-
143
- //socket._socket.on('data', function(chunk) { console.log(chunk.toString('hex'))});
144
-
145
- // Setup the APF keep alive timer
146
- // Websocket does not have timout
147
- // socket.setTimeout(MAX_IDLE);
148
- //socket.on("timeout", () => { ciraTimeoutCount++; parent.debug('apf', "APF timeout, disconnecting."); try { socket.terminate(); } catch (e) { } });
149
- //use on message instead because of websocket
150
- socket.on("message", function (data) {
151
- // use the same debug flag like APF
152
- if (obj.args.debug) { var buf = Buffer.from(data, "binary"); console.log("APF <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
153
- socket.tag.accumulator += data.toString("binary"); // append as binary string
154
-
155
-
156
- try {
157
- // Parse all of the APF data we can
158
- var l = 0;
159
- do { l = ProcessCommand(socket); if (l > 0) { socket.tag.accumulator = socket.tag.accumulator.substring(l); } } while (l > 0);
160
- if (l < 0) { socket.terminate(); }
161
- } catch (e) {
162
- console.log(e);
163
- }
164
- });
165
-
166
- // Process one AFP command
167
- function ProcessCommand(socket) {
168
- var cmd = socket.tag.accumulator.charCodeAt(0);
169
- var len = socket.tag.accumulator.length;
170
- var data = socket.tag.accumulator;
171
- if (len == 0) { return 0; }
172
-
173
- switch (cmd) {
174
- case APFProtocol.KEEPALIVE_REQUEST: {
175
- if (len < 5) return 0;
176
- parent.debug('apfcmd', 'KEEPALIVE_REQUEST');
177
- SendKeepAliveReply(socket, common.ReadInt(data, 1));
178
- return 5;
179
- }
180
- case APFProtocol.KEEPALIVE_REPLY: {
181
- if (len < 5) return 0;
182
- parent.debug('apfcmd', 'KEEPALIVE_REPLY');
183
- return 5;
184
- }
185
- case APFProtocol.PROTOCOLVERSION: {
186
- if (len < 93) return 0;
187
- protocolVersionCount++;
188
- socket.tag.MajorVersion = common.ReadInt(data, 1);
189
- socket.tag.MinorVersion = common.ReadInt(data, 5);
190
- socket.tag.SystemId = guidToStr(common.rstr2hex(data.substring(13, 29))).toLowerCase();
191
- parent.debug('apfcmd', 'PROTOCOLVERSION', socket.tag.MajorVersion, socket.tag.MinorVersion, socket.tag.SystemId);
192
- return 93;
193
- }
194
- case APFProtocol.USERAUTH_REQUEST: {
195
- if (len < 13) return 0;
196
- userAuthRequestCount++;
197
- var usernameLen = common.ReadInt(data, 1);
198
- var username = data.substring(5, 5 + usernameLen);
199
- var serviceNameLen = common.ReadInt(data, 5 + usernameLen);
200
- var serviceName = data.substring(9 + usernameLen, 9 + usernameLen + serviceNameLen);
201
- var methodNameLen = common.ReadInt(data, 9 + usernameLen + serviceNameLen);
202
- var methodName = data.substring(13 + usernameLen + serviceNameLen, 13 + usernameLen + serviceNameLen + methodNameLen);
203
- var passwordLen = 0, password = null;
204
- if (methodName == 'password') {
205
- passwordLen = common.ReadInt(data, 14 + usernameLen + serviceNameLen + methodNameLen);
206
- password = data.substring(18 + usernameLen + serviceNameLen + methodNameLen, 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen);
207
- }
208
- //console.log('APF:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
209
- parent.debug('apfcmd', 'USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
210
-
211
- // Check the APF password
212
- if ((args.mpspass != null) && (password != args.mpspass)) { incorrectPasswordCount++; parent.debug('apf', 'Incorrect password', username, password); SendUserAuthFail(socket); return -1; }
213
-
214
- // Check the APF username, which should be the start of the MeshID.
215
- if (usernameLen != 16) { badUserNameLengthCount++; parent.debug('apf', 'Username length not 16', username, password); SendUserAuthFail(socket); return -1; }
216
- var meshIdStart = '/' + username, mesh = null;
217
- if (obj.parent.webserver.meshes) { for (var i in obj.parent.webserver.meshes) { if (obj.parent.webserver.meshes[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = obj.parent.webserver.meshes[i]; break; } } }
218
- if (mesh == null) { meshNotFoundCount++; parent.debug('apf', 'Mesh not found', username, password); SendUserAuthFail(socket); return -1; }
219
-
220
- // If this is a agent-less mesh, use the device guid 3 times as ID.
221
- if (mesh.mtype == 1) {
222
- // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
223
- var systemid = socket.tag.SystemId.split('-').join('');
224
- var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
225
- var domain = obj.parent.config.domains[mesh.domain];
226
- socket.tag.domain = domain;
227
- socket.tag.domainid = mesh.domain;
228
- socket.tag.name = '';
229
- socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
230
- socket.tag.meshid = mesh._id;
231
- socket.tag.connectTime = Date.now();
232
-
233
- obj.db.Get(socket.tag.nodeid, function (err, nodes) {
234
- if ((nodes == null) || (nodes.length !== 1)) {
235
- // Check if we already have too many devices for this domain
236
- if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
237
- db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) {
238
- if (ismax == true) {
239
- // Too many devices in this domain.
240
- maxDomainDevicesReached++;
241
- console.log('Too many devices on this domain to accept the APF connection. meshid: ' + socket.tag.meshid);
242
- socket.terminate();
243
- } else {
244
- // We are under the limit, create the new device.
245
- // Node is not in the database, add it. Credentials will be empty until added by the user.
246
- var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
247
- obj.db.Set(device);
248
-
249
- // Event the new node
250
- addedDeviceCount++;
251
- var change = 'APF added device ' + socket.tag.name + ' to group ' + mesh.name;
252
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
253
-
254
- // Add the connection to the APF connection list
255
- obj.apfConnections[socket.tag.nodeid] = socket;
256
- // send connectivuty update type 8 for APF
257
- obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 8, 7); // TODO: Right now report power state as "present" (7) until we can poll.
258
- SendUserAuthSuccess(socket); // Notify the auth success on the APF connection
259
- }
260
- });
261
- return;
262
- } else {
263
- // Node is not in the database, add it. Credentials will be empty until added by the user.
264
- var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
265
- obj.db.Set(device);
266
-
267
- // Event the new node
268
- addedDeviceCount++;
269
- var change = 'APF added device ' + socket.tag.name + ' to group ' + mesh.name;
270
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
271
- }
272
- } else {
273
- // Node is already present
274
- var node = nodes[0];
275
- if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
276
- }
277
-
278
- // Add the connection to the APF connection list
279
- obj.apfConnections[socket.tag.nodeid] = socket;
280
- obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 8, 7); // TODO: Right now report power state as "present" (7) until we can poll.
281
- SendUserAuthSuccess(socket); // Notify the auth success on the APF connection
282
- });
283
- } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID
284
- // Intel AMT GUID (socket.tag.SystemId) will be used to search the node
285
- obj.db.getAmtUuidNode(socket.tag.SystemId, function (err, nodes) { // TODO: May need to optimize this request with indexes
286
- if ((nodes == null) || (nodes.length !== 1)) {
287
- // New APF connection for unknown node, disconnect.
288
- unknownNodeCount++;
289
- console.log('APF connection for unknown node. groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
290
- socket.terminate();
291
- return;
292
- }
293
-
294
- // Node is present
295
- var node = nodes[0];
296
- if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
297
- socket.tag.nodeid = node._id;
298
- socket.tag.meshid = mesh._id;
299
- socket.tag.connectTime = Date.now();
300
-
301
- // Add the connection to the APF connection list
302
- obj.apfConnections[socket.tag.nodeid] = socket;
303
- obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 8, 7); // TODO: Right now report power state as "present" (7) until we can poll.
304
- SendUserAuthSuccess(socket); // Notify the auth success on the APF connection
305
- });
306
- } else { // Unknown mesh type
307
- // New APF connection for unknown node, disconnect.
308
- unknownMeshIdCount++;
309
- console.log('APF connection to a unknown group type. groupid: ' + socket.tag.meshid);
310
- socket.terminate();
311
- return;
312
- }
313
- return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen;
314
- }
315
- case APFProtocol.SERVICE_REQUEST: {
316
- if (len < 5) return 0;
317
- var xserviceNameLen = common.ReadInt(data, 1);
318
- if (len < 5 + xserviceNameLen) return 0;
319
- var xserviceName = data.substring(5, 5 + xserviceNameLen);
320
- parent.debug('apfcmd', 'SERVICE_REQUEST', xserviceName);
321
- if (xserviceName == "pfwd@amt.intel.com") { SendServiceAccept(socket, "pfwd@amt.intel.com"); }
322
- if (xserviceName == "auth@amt.intel.com") { SendServiceAccept(socket, "auth@amt.intel.com"); }
323
- return 5 + xserviceNameLen;
324
- }
325
- case APFProtocol.GLOBAL_REQUEST: {
326
- if (len < 14) return 0;
327
- var requestLen = common.ReadInt(data, 1);
328
- if (len < 14 + requestLen) return 0;
329
- var request = data.substring(5, 5 + requestLen);
330
- //var wantResponse = data.charCodeAt(5 + requestLen);
331
-
332
- if (request == "tcpip-forward") {
333
- var addrLen = common.ReadInt(data, 6 + requestLen);
334
- if (len < 14 + requestLen + addrLen) return 0;
335
- var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
336
- var port = common.ReadInt(data, 10 + requestLen + addrLen);
337
- parent.debug('apfcmd', 'GLOBAL_REQUEST', request, addr + ':' + port);
338
- ChangeHostname(socket, addr, socket.tag.SystemId);
339
- if (socket.tag.boundPorts.indexOf(port) == -1) { socket.tag.boundPorts.push(port); }
340
- SendTcpForwardSuccessReply(socket, port);
341
- return 14 + requestLen + addrLen;
342
- }
343
-
344
- if (request == "cancel-tcpip-forward") {
345
- var addrLen = common.ReadInt(data, 6 + requestLen);
346
- if (len < 14 + requestLen + addrLen) return 0;
347
- var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
348
- var port = common.ReadInt(data, 10 + requestLen + addrLen);
349
- parent.debug('apfcmd', 'GLOBAL_REQUEST', request, addr + ':' + port);
350
- var portindex = socket.tag.boundPorts.indexOf(port);
351
- if (portindex >= 0) { socket.tag.boundPorts.splice(portindex, 1); }
352
- SendTcpForwardCancelReply(socket);
353
- return 14 + requestLen + addrLen;
354
- }
355
-
356
- if (request == "udp-send-to@amt.intel.com") {
357
- var addrLen = common.ReadInt(data, 6 + requestLen);
358
- if (len < 26 + requestLen + addrLen) return 0;
359
- var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
360
- var port = common.ReadInt(data, 10 + requestLen + addrLen);
361
- var oaddrLen = common.ReadInt(data, 14 + requestLen + addrLen);
362
- if (len < 26 + requestLen + addrLen + oaddrLen) return 0;
363
- var oaddr = data.substring(18 + requestLen, 18 + requestLen + addrLen);
364
- var oport = common.ReadInt(data, 18 + requestLen + addrLen + oaddrLen);
365
- var datalen = common.ReadInt(data, 22 + requestLen + addrLen + oaddrLen);
366
- if (len < 26 + requestLen + addrLen + oaddrLen + datalen) return 0;
367
- parent.debug('apfcmd', 'GLOBAL_REQUEST', request, addr + ':' + port, oaddr + ':' + oport, datalen);
368
- // TODO
369
- return 26 + requestLen + addrLen + oaddrLen + datalen;
370
- }
371
-
372
- return 6 + requestLen;
373
- }
374
- case APFProtocol.CHANNEL_OPEN: {
375
- if (len < 33) return 0;
376
- var ChannelTypeLength = common.ReadInt(data, 1);
377
- if (len < (33 + ChannelTypeLength)) return 0;
378
-
379
- // Decode channel identifiers and window size
380
- var ChannelType = data.substring(5, 5 + ChannelTypeLength);
381
- var SenderChannel = common.ReadInt(data, 5 + ChannelTypeLength);
382
- var WindowSize = common.ReadInt(data, 9 + ChannelTypeLength);
383
-
384
- // Decode the target
385
- var TargetLen = common.ReadInt(data, 17 + ChannelTypeLength);
386
- if (len < (33 + ChannelTypeLength + TargetLen)) return 0;
387
- var Target = data.substring(21 + ChannelTypeLength, 21 + ChannelTypeLength + TargetLen);
388
- var TargetPort = common.ReadInt(data, 21 + ChannelTypeLength + TargetLen);
389
-
390
- // Decode the source
391
- var SourceLen = common.ReadInt(data, 25 + ChannelTypeLength + TargetLen);
392
- if (len < (33 + ChannelTypeLength + TargetLen + SourceLen)) return 0;
393
- var Source = data.substring(29 + ChannelTypeLength + TargetLen, 29 + ChannelTypeLength + TargetLen + SourceLen);
394
- var SourcePort = common.ReadInt(data, 29 + ChannelTypeLength + TargetLen + SourceLen);
395
-
396
- channelOpenCount++;
397
- parent.debug('apfcmd', 'CHANNEL_OPEN', ChannelType, SenderChannel, WindowSize, Target + ':' + TargetPort, Source + ':' + SourcePort);
398
-
399
- // Check if we understand this channel type
400
- //if (ChannelType.toLowerCase() == "direct-tcpip")
401
- {
402
- // We don't understand this channel type, send an error back
403
- SendChannelOpenFailure(socket, SenderChannel, APFChannelOpenFailureReasonCode.UnknownChannelType);
404
- return 33 + ChannelTypeLength + TargetLen + SourceLen;
405
- }
406
-
407
- /*
408
- // This is a correct connection. Lets get it setup
409
- var MeshAmtEventEndpoint = { ServerChannel: GetNextBindId(), AmtChannel: SenderChannel, MaxWindowSize: 2048, CurrentWindowSize:2048, SendWindow: WindowSize, InfoHeader: "Target: " + Target + ":" + TargetPort + ", Source: " + Source + ":" + SourcePort};
410
- // TODO: Connect this socket for a WSMAN event
411
- SendChannelOpenConfirmation(socket, SenderChannel, MeshAmtEventEndpoint.ServerChannel, MeshAmtEventEndpoint.MaxWindowSize);
412
- */
413
-
414
- return 33 + ChannelTypeLength + TargetLen + SourceLen;
415
- }
416
- case APFProtocol.CHANNEL_OPEN_CONFIRMATION:
417
- {
418
- if (len < 17) return 0;
419
- var RecipientChannel = common.ReadInt(data, 1);
420
- var SenderChannel = common.ReadInt(data, 5);
421
- var WindowSize = common.ReadInt(data, 9);
422
- socket.tag.activetunnels++;
423
- var cirachannel = socket.tag.channels[RecipientChannel];
424
- if (cirachannel == null) { /*console.log("APF Error in CHANNEL_OPEN_CONFIRMATION: Unable to find channelid " + RecipientChannel);*/ return 17; }
425
- cirachannel.amtchannelid = SenderChannel;
426
- cirachannel.sendcredits = cirachannel.amtCiraWindow = WindowSize;
427
- channelOpenConfirmCount++;
428
- parent.debug('apfcmd', 'CHANNEL_OPEN_CONFIRMATION', RecipientChannel, SenderChannel, WindowSize);
429
- if (cirachannel.closing == 1) {
430
- // Close this channel
431
- SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
432
- } else {
433
- cirachannel.state = 2;
434
- // Send any pending data
435
- if (cirachannel.sendBuffer != null) {
436
- if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
437
- // Send the entire pending buffer
438
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
439
- cirachannel.sendcredits -= cirachannel.sendBuffer.length;
440
- delete cirachannel.sendBuffer;
441
- if (cirachannel.onSendOk) { cirachannel.onSendOk(cirachannel); }
442
- } else {
443
- // Send a part of the pending buffer
444
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer.substring(0, cirachannel.sendcredits));
445
- cirachannel.sendBuffer = cirachannel.sendBuffer.substring(cirachannel.sendcredits);
446
- cirachannel.sendcredits = 0;
447
- }
448
- }
449
- // Indicate the channel is open
450
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
451
- }
452
- return 17;
453
- }
454
- case APFProtocol.CHANNEL_OPEN_FAILURE:
455
- {
456
- if (len < 17) return 0;
457
- var RecipientChannel = common.ReadInt(data, 1);
458
- var ReasonCode = common.ReadInt(data, 5);
459
- channelOpenFailCount++;
460
- parent.debug('apfcmd', 'CHANNEL_OPEN_FAILURE', RecipientChannel, ReasonCode);
461
- var cirachannel = socket.tag.channels[RecipientChannel];
462
- if (cirachannel == null) { console.log("APF Error in CHANNEL_OPEN_FAILURE: Unable to find channelid " + RecipientChannel); return 17; }
463
- if (cirachannel.state > 0) {
464
- cirachannel.state = 0;
465
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
466
- delete socket.tag.channels[RecipientChannel];
467
- }
468
- return 17;
469
- }
470
- case APFProtocol.CHANNEL_CLOSE:
471
- {
472
- if (len < 5) return 0;
473
- var RecipientChannel = common.ReadInt(data, 1);
474
- channelCloseCount++;
475
- parent.debug('apfcmd', 'CHANNEL_CLOSE', RecipientChannel);
476
- var cirachannel = socket.tag.channels[RecipientChannel];
477
- if (cirachannel == null) { console.log("APF Error in CHANNEL_CLOSE: Unable to find channelid " + RecipientChannel); return 5; }
478
- socket.tag.activetunnels--;
479
- if (cirachannel.state > 0) {
480
- cirachannel.state = 0;
481
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
482
- SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
483
- delete socket.tag.channels[RecipientChannel];
484
- }
485
- return 5;
486
- }
487
- case APFProtocol.CHANNEL_WINDOW_ADJUST:
488
- {
489
- if (len < 9) return 0;
490
- var RecipientChannel = common.ReadInt(data, 1);
491
- var ByteToAdd = common.ReadInt(data, 5);
492
- var cirachannel = socket.tag.channels[RecipientChannel];
493
- if (cirachannel == null) { console.log("APF Error in CHANNEL_WINDOW_ADJUST: Unable to find channelid " + RecipientChannel); return 9; }
494
- cirachannel.sendcredits += ByteToAdd;
495
- parent.debug('apfcmd', 'CHANNEL_WINDOW_ADJUST', RecipientChannel, ByteToAdd, cirachannel.sendcredits);
496
- if (cirachannel.state == 2 && cirachannel.sendBuffer != null) {
497
- // Compute how much data we can send
498
- if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
499
- // Send the entire pending buffer
500
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
501
- cirachannel.sendcredits -= cirachannel.sendBuffer.length;
502
- delete cirachannel.sendBuffer;
503
- if (cirachannel.onSendOk) { cirachannel.onSendOk(cirachannel); }
504
- } else {
505
- // Send a part of the pending buffer
506
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer.substring(0, cirachannel.sendcredits));
507
- cirachannel.sendBuffer = cirachannel.sendBuffer.substring(cirachannel.sendcredits);
508
- cirachannel.sendcredits = 0;
509
- }
510
- }
511
- return 9;
512
- }
513
- case APFProtocol.CHANNEL_DATA:
514
- {
515
- if (len < 9) return 0;
516
- var RecipientChannel = common.ReadInt(data, 1);
517
- var LengthOfData = common.ReadInt(data, 5);
518
- if (len < (9 + LengthOfData)) return 0;
519
- parent.debug('apfcmddata', 'CHANNEL_DATA', RecipientChannel, LengthOfData);
520
- var cirachannel = socket.tag.channels[RecipientChannel];
521
- if (cirachannel == null) { console.log("APF Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return 9 + LengthOfData; }
522
- cirachannel.amtpendingcredits += LengthOfData;
523
- if (cirachannel.onData) cirachannel.onData(cirachannel, data.substring(9, 9 + LengthOfData));
524
- if (cirachannel.amtpendingcredits > (cirachannel.ciraWindow / 2)) {
525
- SendChannelWindowAdjust(cirachannel.socket, cirachannel.amtchannelid, cirachannel.amtpendingcredits); // Adjust the buffer window
526
- cirachannel.amtpendingcredits = 0;
527
- }
528
- return 9 + LengthOfData;
529
- }
530
- case APFProtocol.DISCONNECT:
531
- {
532
- if (len < 7) return 0;
533
- var ReasonCode = common.ReadInt(data, 1);
534
- disconnectCommandCount++;
535
- parent.debug('apfcmd', 'DISCONNECT', ReasonCode);
536
- try { delete obj.apfConnections[socket.tag.nodeid]; } catch (e) { }
537
- obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8);
538
- return 7;
539
- }
540
- default:
541
- {
542
- parent.debug('apfcmd', 'Unknown APF command: ' + cmd);
543
- return -1;
544
- }
545
- }
546
- }
547
-
548
- socket.addListener("close", function () {
549
- socketClosedCount++;
550
- parent.debug('apf', 'APF connection closed');
551
- try { delete obj.apfConnections[socket.tag.nodeid]; } catch (e) { }
552
- obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8);
553
- });
554
-
555
- socket.addListener("error", function (e) {
556
- socketErrorCount++;
557
- console.log("APF Error: " + e);
558
- });
559
-
560
- }
561
-
562
- // Disconnect APF tunnel
563
- obj.close = function (socket) {
564
- try { socket.terminate(); } catch (e) { }
565
- try { delete obj.apfConnections[socket.tag.nodeid]; } catch (e) { }
566
- obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8);
567
- };
568
-
569
- function SendServiceAccept(socket, service) {
570
- Write(socket, String.fromCharCode(APFProtocol.SERVICE_ACCEPT) + common.IntToStr(service.length) + service);
571
- }
572
-
573
- function SendTcpForwardSuccessReply(socket, port) {
574
- Write(socket, String.fromCharCode(APFProtocol.REQUEST_SUCCESS) + common.IntToStr(port));
575
- }
576
-
577
- function SendTcpForwardCancelReply(socket) {
578
- Write(socket, String.fromCharCode(APFProtocol.REQUEST_SUCCESS));
579
- }
580
-
581
- /*
582
- function SendKeepAliveRequest(socket, cookie) {
583
- Write(socket, String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + common.IntToStr(cookie));
584
- }
585
- */
586
-
587
- function SendKeepAliveReply(socket, cookie) {
588
- Write(socket, String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + common.IntToStr(cookie));
589
- }
590
-
591
- function SendChannelOpenFailure(socket, senderChannel, reasonCode) {
592
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + common.IntToStr(senderChannel) + common.IntToStr(reasonCode) + common.IntToStr(0) + common.IntToStr(0));
593
- }
594
-
595
- /*
596
- function SendChannelOpenConfirmation(socket, recipientChannelId, senderChannelId, initialWindowSize) {
597
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + common.IntToStr(recipientChannelId) + common.IntToStr(senderChannelId) + common.IntToStr(initialWindowSize) + common.IntToStr(-1));
598
- }
599
- */
600
-
601
- function SendChannelOpen(socket, direct, channelid, windowsize, target, targetport, source, sourceport) {
602
- var connectionType = ((direct == true) ? "direct-tcpip" : "forwarded-tcpip");
603
- if ((target == null) || (target == null)) target = ''; // TODO: Reports of target being undefined that causes target.length to fail. This is a hack.
604
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_OPEN) + common.IntToStr(connectionType.length) + connectionType + common.IntToStr(channelid) + common.IntToStr(windowsize) + common.IntToStr(-1) + common.IntToStr(target.length) + target + common.IntToStr(targetport) + common.IntToStr(source.length) + source + common.IntToStr(sourceport));
605
- }
606
-
607
- function SendChannelClose(socket, channelid) {
608
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + common.IntToStr(channelid));
609
- }
610
-
611
- function SendChannelData(socket, channelid, data) {
612
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_DATA) + common.IntToStr(channelid) + common.IntToStr(data.length) + data);
613
- }
614
-
615
- function SendChannelWindowAdjust(socket, channelid, bytestoadd) {
616
- parent.debug('apfcmd', 'SendChannelWindowAdjust', channelid, bytestoadd);
617
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + common.IntToStr(channelid) + common.IntToStr(bytestoadd));
618
- }
619
-
620
- /*
621
- function SendDisconnect(socket, reasonCode) {
622
- Write(socket, String.fromCharCode(APFProtocol.DISCONNECT) + common.IntToStr(reasonCode) + common.ShortToStr(0));
623
- }
624
- */
625
-
626
- function SendUserAuthFail(socket) {
627
- Write(socket, String.fromCharCode(APFProtocol.USERAUTH_FAILURE) + common.IntToStr(8) + 'password' + common.ShortToStr(0));
628
- }
629
-
630
- function SendUserAuthSuccess(socket) {
631
- Write(socket, String.fromCharCode(APFProtocol.USERAUTH_SUCCESS));
632
- }
633
-
634
- function Write(socket, data) {
635
- if (obj.args.debug) {
636
- // Print out sent bytes
637
- var buf = Buffer.from(data, "binary");
638
- console.log('APF --> (' + buf.length + '):' + buf.toString('hex'));
639
- socket.send(buf);
640
- } else {
641
- socket.send(Buffer.from(data, "binary"));
642
- }
643
- }
644
-
645
- // Setup a new channel to a nodeid
646
- obj.SetupChannelToNode = function (nodeid, targetport) {
647
- var apfconn = obj.apfConnections[nodeid];
648
- if (apfconn == null) return null;
649
- return obj.SetupChannel(apfconn, targetport);
650
- }
651
-
652
- obj.SetupChannel = function (socket, targetport) {
653
- var sourceport = (socket.tag.nextsourceport++ % 30000) + 1024;
654
- var cirachannel = { targetport: targetport, channelid: socket.tag.nextchannelid++, socket: socket, state: 1, sendcredits: 0, amtpendingcredits: 0, amtCiraWindow: 0, ciraWindow: 32768 };
655
- SendChannelOpen(socket, false, cirachannel.channelid, cirachannel.ciraWindow, socket.tag.host, targetport, "1.2.3.4", sourceport);
656
-
657
- // This function writes data to this APF channel
658
- cirachannel.write = function (data) {
659
- if (cirachannel.state == 0) return false;
660
- if (cirachannel.state == 1 || cirachannel.sendcredits == 0 || cirachannel.sendBuffer != null) {
661
- // Channel is connected, but we are out of credits. Add the data to the outbound buffer.
662
- if (cirachannel.sendBuffer == null) { cirachannel.sendBuffer = data; } else { cirachannel.sendBuffer += data; }
663
- return true;
664
- }
665
- // Compute how much data we can send
666
- if (data.length <= cirachannel.sendcredits) {
667
- // Send the entire message
668
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, data);
669
- cirachannel.sendcredits -= data.length;
670
- return true;
671
- }
672
- // Send a part of the message
673
- cirachannel.sendBuffer = data.substring(cirachannel.sendcredits);
674
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, data.substring(0, cirachannel.sendcredits));
675
- cirachannel.sendcredits = 0;
676
- return false;
677
- };
678
-
679
- // This function closes this APF channel
680
- cirachannel.close = function () {
681
- if (cirachannel.state == 0 || cirachannel.closing == 1) return;
682
- if (cirachannel.state == 1) { cirachannel.closing = 1; cirachannel.state = 0; if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); } return; }
683
- cirachannel.state = 0;
684
- cirachannel.closing = 1;
685
- SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
686
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
687
- };
688
-
689
- socket.tag.channels[cirachannel.channelid] = cirachannel;
690
- return cirachannel;
691
- };
692
-
693
- function ChangeHostname(socket, host, systemid) {
694
- if (socket.tag.host === host) return; // Nothing to change
695
- socket.tag.host = host;
696
-
697
- // Change the device
698
- obj.db.Get(socket.tag.nodeid, function (err, nodes) {
699
- if ((nodes == null) || (nodes.length !== 1)) return;
700
- var node = nodes[0];
701
-
702
- // See if any changes need to be made
703
- if ((node.intelamt != null) && (node.intelamt.host == host) && (node.name != null) && (node.name != '') && (node.intelamt.state == 2)) return;
704
-
705
- // Get the mesh for this device
706
- obj.db.Get(node.meshid, function (err, meshes) {
707
- if ((meshes == null) || (meshes.length !== 1)) return;
708
- var mesh = meshes[0];
709
-
710
- // Ready the node change event
711
- var changes = ['host'], event = { etype: 'node', action: 'changenode', nodeid: node._id };
712
- event.msg = +": ";
713
-
714
- // Make the change & save
715
- if (node.intelamt == null) node.intelamt = {};
716
- node.intelamt.host = host;
717
- node.intelamt.state = 2; // TODO: this is not real AMT state
718
- if (((node.name == null) || (node.name == '')) && (host != null) && (host != '')) { node.name = host.split('.')[0]; } // If this system has no name, set it to the start of the domain name.
719
- if (((node.name == null) || (node.name == '')) && (systemid != null)) { node.name = systemid; } // If this system still has no name, set it to the system GUID.
720
- obj.db.Set(node);
721
-
722
- // Event the node change
723
- event.msg = 'APF changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', ');
724
- event.node = parent.webserver.CloneSafeNode(node);
725
- if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
726
- obj.parent.DispatchEvent(['*', node.meshid], obj, event);
727
- });
728
- });
729
- }
730
-
731
- 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); }
732
-
733
- return obj;
734
-};
meshagent.js
+1
-1
@@ -1475,7 +1475,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1475
1476
// Change the current core information string and event it
1477
function ChangeAgentCoreInfo(command) {
1478
- if (obj.agentInfo.capabilities & 0x40) return;
1478
+ if ((obj.agentInfo == null) || (obj.agentInfo.capabilities & 0x40)) return;
1479
if ((command == null) || (command == null)) return; // Safety, should never happen.
1480
1481
// If the device is pending a change, hold.
meshcentral.js
-4
@@ -26,7 +26,6 @@ function CreateMeshCentralServer(config, args) {
26
obj.webserver = null;
27
obj.redirserver = null;
28
obj.mpsserver = null;
29
- obj.apfserver = null;
29
obj.mqttbroker = null;
30
obj.swarmserver = null;
31
obj.mailserver = null;
@@ -1318,9 +1317,6 @@ function CreateMeshCentralServer(config, args) {
1317
if ((obj.args.sessiontime != null) && ((typeof obj.args.sessiontime != 'number') || (obj.args.sessiontime < 1))) { delete obj.args.sessiontime; }
1318
if (!obj.args.sessionkey) { obj.args.sessionkey = buf.toString('hex').toUpperCase(); }
1319
1321
- // Create APF server to hook into webserver
1322
- obj.apfserver = require('./apfserver.js').CreateApfServer(obj, obj.db, obj.args);
1323
-
1320
// Create MQTT Broker to hook into webserver and mpsserver
1321
if ((typeof obj.config.settings.mqtt == 'object') && (typeof obj.config.settings.mqtt.auth == 'object') && (typeof obj.config.settings.mqtt.auth.keyid == 'string') && (typeof obj.config.settings.mqtt.auth.key == 'string')) { obj.mqttbroker = require("./mqttbroker.js").CreateMQTTBroker(obj, obj.db, obj.args); }
1322
meshuser.js
+4
-1
@@ -4670,9 +4670,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4670
if ((state == null) || (state.connectivity & 4) == 0) break;
4671
} else if (command.mode == 2) {
4672
if (parent.parent.mpsserver.ciraConnections[command.nodeid] == null) break;
4673
- } else if (command.mode == 3) {
4673
+ }
4674
+ /*
4675
+ else if (command.mode == 3) {
4676
if (parent.parent.apfserver.apfConnections[command.nodeid] == null) break;
4677
}
4678
+ */
4679
4680
// Get the node and the rights for this node
4681
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
mpsserver.js
+420
-386
@@ -144,11 +144,13 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
144
145
// Delay setting the connectivity state by 300ms to allow time for CIRA port mappings to be established
146
// Report power state as "present" (7) until Intel AMT manager starts polling for power state.
147
- function delayedSetConnectivityState(meshid, nodeid, connectTime) {
148
- var f = function setConnFunc() { if (obj.ciraConnections[setConnFunc.nodeid] != null) { obj.parent.SetConnectivityState(setConnFunc.meshid, setConnFunc.nodeid, setConnFunc.connectTime, 2, 7); } }
147
+ function delayedSetConnectivityState(meshid, nodeid, connectTime, connType) {
148
+ if (nodeid.startsWith('*')) return; // Don't set connectivity state for Intel AMT self agent relay
149
+ var f = function setConnFunc() { if (obj.ciraConnections[setConnFunc.nodeid] != null) { obj.parent.SetConnectivityState(setConnFunc.meshid, setConnFunc.nodeid, setConnFunc.connectTime, setConnFunc.connType, 7); } }
150
f.nodeid = nodeid;
151
f.meshid = meshid;
152
f.connectTime = connectTime;
153
+ f.connType = connType;
154
setTimeout(f, 300);
155
}
156
@@ -220,13 +222,47 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
222
return packet_len;
223
}
224
225
+ obj.onWebSocketConnection = function (socket) {
226
+ connectionCount++;
227
+ // connType: 2 = CIRA, 8 = Relay
228
+ socket.tag = { first: true, connType: 2, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], websocket: true, socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
229
+ socket.websocket = 1;
230
+ parent.debug('mps', "New CIRA websocket connection");
231
+
232
+ socket.on('message', function (data) {
233
+ if (args.mpsdebug) { var buf = Buffer.from(data, 'binary'); console.log("MPS <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
234
+ this.tag.accumulator += data.toString('binary'); // Append as binary string
235
+ try {
236
+ // Parse all of the APF data we can
237
+ var l = 0;
238
+ do { l = ProcessCommand(this); if (l > 0) { this.tag.accumulator = this.tag.accumulator.substring(l); } } while (l > 0);
239
+ if (l < 0) { this.terminate(); }
240
+ } catch (e) {
241
+ console.log(e);
242
+ }
243
+ });
244
+
245
+ socket.addListener('close', function () {
246
+ socketClosedCount++;
247
+ parent.debug('mps', "CIRA websocket closed", this.tag.meshid, this.tag.nodeid);
248
+ try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
249
+ if (!this.tag.nodeid.startsWith('*')) { obj.parent.ClearConnectivityState(this.tag.meshid, this.tag.nodeid, this.tag.connType); }
250
+ });
251
+
252
+ socket.addListener('error', function (e) {
253
+ socketErrorCount++;
254
+ parent.debug('mps', "CIRA websocket connection error", e);
255
+ });
256
+ }
257
+
258
// Called when a new TLS/TCP connection is accepted
259
function onConnection(socket) {
260
connectionCount++;
261
+ // connType: 2 = CIRA, 8 = Relay
262
if (obj.args.mpstlsoffload) {
227
- socket.tag = { first: true, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
263
+ socket.tag = { first: true, connType: 2, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
264
} else {
229
- socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
265
+ socket.tag = { first: true, connType: 2, clientCert: socket.getPeerCertificate(true), accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
266
}
267
socket.setEncoding('binary');
268
parent.debug('mps', "New CIRA connection");
@@ -235,6 +271,19 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
271
socket.setTimeout(MAX_IDLE);
272
socket.on('timeout', () => { ciraTimeoutCount++; parent.debug('mps', "CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } });
273
274
+ socket.addListener('close', function () {
275
+ socketClosedCount++;
276
+ parent.debug('mps', 'CIRA connection closed');
277
+ try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
278
+ obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connType);
279
+ });
280
+
281
+ socket.addListener('error', function (e) {
282
+ socketErrorCount++;
283
+ parent.debug('mps', 'CIRA connection error', e);
284
+ //console.log("MPS Error: " + socket.remoteAddress);
285
+ });
286
+
287
socket.addListener('data', function (data) {
288
if (args.mpsdebug) { var buf = Buffer.from(data, 'binary'); console.log("MPS --> (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
289
socket.tag.accumulator += data;
@@ -334,8 +383,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
383
384
// Add the connection to the MPS connection list
385
obj.ciraConnections[socket.tag.nodeid] = socket;
337
- //obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll.
338
- delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
386
+ delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
387
}
388
});
389
return;
@@ -365,7 +413,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
413
414
// Add the connection to the MPS connection list
415
obj.ciraConnections[socket.tag.nodeid] = socket;
368
- delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
416
+ delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
417
});
418
} else {
419
// This node connected without certificate authentication, use password auth
@@ -382,355 +430,294 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
430
console.log(e);
431
}
432
});
433
+ }
434
386
- // Process one APF command
387
- function ProcessCommand(socket) {
388
- var cmd = socket.tag.accumulator.charCodeAt(0);
389
- var len = socket.tag.accumulator.length;
390
- var data = socket.tag.accumulator;
391
- if (len == 0) { return 0; }
392
-
393
- switch (cmd) {
394
- case APFProtocol.KEEPALIVE_REQUEST: {
395
- if (len < 5) return 0;
396
- parent.debug('mpscmd', '--> KEEPALIVE_REQUEST');
397
- SendKeepAliveReply(socket, common.ReadInt(data, 1));
398
- return 5;
399
- }
400
- case APFProtocol.KEEPALIVE_REPLY: {
401
- if (len < 5) return 0;
402
- parent.debug('mpscmd', '--> KEEPALIVE_REPLY');
403
- return 5;
404
- }
405
- case APFProtocol.PROTOCOLVERSION: {
406
- if (len < 93) return 0;
407
- protocolVersionCount++;
408
- socket.tag.MajorVersion = common.ReadInt(data, 1);
409
- socket.tag.MinorVersion = common.ReadInt(data, 5);
410
- socket.tag.SystemId = guidToStr(common.rstr2hex(data.substring(13, 29))).toLowerCase();
411
- parent.debug('mpscmd', '--> PROTOCOLVERSION', socket.tag.MajorVersion, socket.tag.MinorVersion, socket.tag.SystemId);
412
- return 93;
435
+ // Process one APF command
436
+ function ProcessCommand(socket) {
437
+ var cmd = socket.tag.accumulator.charCodeAt(0);
438
+ var len = socket.tag.accumulator.length;
439
+ var data = socket.tag.accumulator;
440
+ if (len == 0) { return 0; }
441
+
442
+ switch (cmd) {
443
+ case APFProtocol.KEEPALIVE_REQUEST: {
444
+ if (len < 5) return 0;
445
+ parent.debug('mpscmd', '--> KEEPALIVE_REQUEST');
446
+ SendKeepAliveReply(socket, common.ReadInt(data, 1));
447
+ return 5;
448
+ }
449
+ case APFProtocol.KEEPALIVE_REPLY: {
450
+ if (len < 5) return 0;
451
+ parent.debug('mpscmd', '--> KEEPALIVE_REPLY');
452
+ return 5;
453
+ }
454
+ case APFProtocol.PROTOCOLVERSION: {
455
+ if (len < 93) return 0;
456
+ protocolVersionCount++;
457
+ socket.tag.MajorVersion = common.ReadInt(data, 1);
458
+ socket.tag.MinorVersion = common.ReadInt(data, 5);
459
+ socket.tag.SystemId = guidToStr(common.rstr2hex(data.substring(13, 29))).toLowerCase();
460
+ parent.debug('mpscmd', '--> PROTOCOLVERSION', socket.tag.MajorVersion, socket.tag.MinorVersion, socket.tag.SystemId);
461
+ return 93;
462
+ }
463
+ case APFProtocol.USERAUTH_REQUEST: {
464
+ if (len < 13) return 0;
465
+ userAuthRequestCount++;
466
+ var usernameLen = common.ReadInt(data, 1);
467
+ var username = data.substring(5, 5 + usernameLen);
468
+ var serviceNameLen = common.ReadInt(data, 5 + usernameLen);
469
+ var serviceName = data.substring(9 + usernameLen, 9 + usernameLen + serviceNameLen);
470
+ var methodNameLen = common.ReadInt(data, 9 + usernameLen + serviceNameLen);
471
+ var methodName = data.substring(13 + usernameLen + serviceNameLen, 13 + usernameLen + serviceNameLen + methodNameLen);
472
+ var passwordLen = 0, password = null;
473
+ if (methodName == 'password') {
474
+ passwordLen = common.ReadInt(data, 14 + usernameLen + serviceNameLen + methodNameLen);
475
+ password = data.substring(18 + usernameLen + serviceNameLen + methodNameLen, 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen);
476
}
414
- case APFProtocol.USERAUTH_REQUEST: {
415
- if (len < 13) return 0;
416
- userAuthRequestCount++;
417
- var usernameLen = common.ReadInt(data, 1);
418
- var username = data.substring(5, 5 + usernameLen);
419
- var serviceNameLen = common.ReadInt(data, 5 + usernameLen);
420
- var serviceName = data.substring(9 + usernameLen, 9 + usernameLen + serviceNameLen);
421
- var methodNameLen = common.ReadInt(data, 9 + usernameLen + serviceNameLen);
422
- var methodName = data.substring(13 + usernameLen + serviceNameLen, 13 + usernameLen + serviceNameLen + methodNameLen);
423
- var passwordLen = 0, password = null;
424
- if (methodName == 'password') {
425
- passwordLen = common.ReadInt(data, 14 + usernameLen + serviceNameLen + methodNameLen);
426
- password = data.substring(18 + usernameLen + serviceNameLen + methodNameLen, 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen);
427
- }
428
- //console.log('MPS:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
429
- parent.debug('mpscmd', '--> USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
430
-
431
- // Check the CIRA password
432
- if ((args.mpspass != null) && (password != args.mpspass)) { incorrectPasswordCount++; parent.debug('mps', 'Incorrect password', username, password); SendUserAuthFail(socket); return -1; }
433
-
434
- // Check the CIRA username, which should be the start of the MeshID.
435
- if (usernameLen != 16) { badUserNameLengthCount++; parent.debug('mps', 'Username length not 16', username, password); SendUserAuthFail(socket); return -1; }
436
- var meshIdStart = '/' + username, mesh = null;
437
- if (obj.parent.webserver.meshes) { for (var i in obj.parent.webserver.meshes) { if (obj.parent.webserver.meshes[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = obj.parent.webserver.meshes[i]; break; } } }
438
- if (mesh == null) { meshNotFoundCount++; parent.debug('mps', 'Device group not found', username, password); SendUserAuthFail(socket); return -1; }
439
-
440
- // If this is a agent-less mesh, use the device guid 3 times as ID.
441
- if (mesh.mtype == 1) {
442
- // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
443
- var systemid = socket.tag.SystemId.split('-').join('');
444
- var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
445
- var domain = obj.parent.config.domains[mesh.domain];
446
- socket.tag.domain = domain;
447
- socket.tag.domainid = mesh.domain;
448
- socket.tag.name = '';
449
- socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
450
- socket.tag.meshid = mesh._id;
451
- socket.tag.connectTime = Date.now();
452
-
453
- obj.db.Get(socket.tag.nodeid, function (err, nodes) {
454
- if ((nodes == null) || (nodes.length !== 1)) {
455
- // Check if we already have too many devices for this domain
456
- if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
457
- db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) {
458
- if (ismax == true) {
459
- // Too many devices in this domain.
460
- maxDomainDevicesReached++;
461
- console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid);
462
- socket.end();
463
- } else {
464
- // We are under the limit, create the new device.
465
- // Node is not in the database, add it. Credentials will be empty until added by the user.
466
- var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
467
- obj.db.Set(device);
468
-
469
- // Event the new node
470
- addedDeviceCount++;
471
- var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
472
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
473
-
474
- // Add the connection to the MPS connection list
475
- obj.ciraConnections[socket.tag.nodeid] = socket;
476
- delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
477
- SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
478
- }
479
- });
480
- return;
481
- } else {
482
- // Node is not in the database, add it. Credentials will be empty until added by the user.
483
- var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
484
- obj.db.Set(device);
477
+ //console.log('MPS:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
478
+ parent.debug('mpscmd', '--> USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
479
+
480
+ // Check the CIRA password
481
+ if ((args.mpspass != null) && (password != args.mpspass)) { incorrectPasswordCount++; parent.debug('mps', 'Incorrect password', username, password); SendUserAuthFail(socket); return -1; }
482
+
483
+ // Check the CIRA username, which should be the start of the MeshID.
484
+ if (usernameLen != 16) { badUserNameLengthCount++; parent.debug('mps', 'Username length not 16', username, password); SendUserAuthFail(socket); return -1; }
485
+ var meshIdStart = '/' + username, mesh = null;
486
+ if (obj.parent.webserver.meshes) { for (var i in obj.parent.webserver.meshes) { if (obj.parent.webserver.meshes[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = obj.parent.webserver.meshes[i]; break; } } }
487
+ if (mesh == null) { meshNotFoundCount++; parent.debug('mps', 'Device group not found', username, password); SendUserAuthFail(socket); return -1; }
488
+
489
+ // If this is a agent-less mesh, use the device guid 3 times as ID.
490
+ if (mesh.mtype == 1) {
491
+ // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
492
+ var systemid = socket.tag.SystemId.split('-').join('');
493
+ var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
494
+ var domain = obj.parent.config.domains[mesh.domain];
495
+ socket.tag.domain = domain;
496
+ socket.tag.domainid = mesh.domain;
497
+ socket.tag.name = '';
498
+ socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
499
+ socket.tag.meshid = mesh._id;
500
+ socket.tag.connectTime = Date.now();
501
486
- // Event the new node
487
- addedDeviceCount++;
488
- var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
489
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
490
- }
502
+ obj.db.Get(socket.tag.nodeid, function (err, nodes) {
503
+ if ((nodes == null) || (nodes.length !== 1)) {
504
+ // Check if we already have too many devices for this domain
505
+ if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
506
+ db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) {
507
+ if (ismax == true) {
508
+ // Too many devices in this domain.
509
+ maxDomainDevicesReached++;
510
+ console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid);
511
+ socket.end();
512
+ } else {
513
+ // We are under the limit, create the new device.
514
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
515
+ var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
516
+ obj.db.Set(device);
517
+
518
+ // Event the new node
519
+ addedDeviceCount++;
520
+ var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
521
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
522
+
523
+ // Add the connection to the MPS connection list
524
+ obj.ciraConnections[socket.tag.nodeid] = socket;
525
+ delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
526
+ SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
527
+ }
528
+ });
529
+ return;
530
} else {
492
- // Node is already present
493
- var node = nodes[0];
494
- socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
495
- if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
531
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
532
+ var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
533
+ obj.db.Set(device);
534
+
535
+ // Event the new node
536
+ addedDeviceCount++;
537
+ var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
538
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
539
}
540
+ } else {
541
+ // Node is already present
542
+ var node = nodes[0];
543
+ socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
544
+ if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
545
+ }
546
498
- // Add the connection to the MPS connection list
499
- obj.ciraConnections[socket.tag.nodeid] = socket;
500
- delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
501
- SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
502
- });
503
- } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID
504
- // Intel AMT GUID (socket.tag.SystemId) will be used to search the node
505
- obj.db.getAmtUuidNode(socket.tag.SystemId, function (err, nodes) { // TODO: May need to optimize this request with indexes
506
- if ((nodes == null) || (nodes.length === 0) || (obj.parent.webserver.meshes == null)) {
507
- // New CIRA connection for unknown node, disconnect.
508
- unknownNodeCount++;
509
- console.log('CIRA connection for unknown node. groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
510
- socket.end();
511
- return;
512
- }
547
+ // Add the connection to the MPS connection list
548
+ obj.ciraConnections[socket.tag.nodeid] = socket;
549
+ delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
550
+ SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
551
+ });
552
+ } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID
553
+ // Intel AMT GUID (socket.tag.SystemId) will be used to search the node
554
+ obj.db.getAmtUuidNode(socket.tag.SystemId, function (err, nodes) { // TODO: May need to optimize this request with indexes
555
+ if ((nodes == null) || (nodes.length === 0) || (obj.parent.webserver.meshes == null)) {
556
+ // New CIRA connection for unknown node, disconnect.
557
+ unknownNodeCount++;
558
+ console.log('CIRA connection for unknown node. groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
559
+ socket.end();
560
+ return;
561
+ }
562
514
- // Looking at nodes that match this UUID, select one in the same domain and mesh type.
515
- var node = null;
516
- for (var i in nodes) {
517
- if (mesh.domain == nodes[i].domain) {
518
- var nodemesh = obj.parent.webserver.meshes[nodes[i].meshid];
519
- if ((nodemesh != null) && (nodemesh.mtype == 2)) { node = nodes[i]; }
520
- }
563
+ // Looking at nodes that match this UUID, select one in the same domain and mesh type.
564
+ var node = null;
565
+ for (var i in nodes) {
566
+ if (mesh.domain == nodes[i].domain) {
567
+ var nodemesh = obj.parent.webserver.meshes[nodes[i].meshid];
568
+ if ((nodemesh != null) && (nodemesh.mtype == 2)) { node = nodes[i]; }
569
}
570
+ }
571
523
- if (node == null) {
524
- // New CIRA connection for unknown node, disconnect.
525
- unknownNodeCount++;
526
- console.log('CIRA connection for unknown node. candidate(s): ' + nodes.length + ', groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
527
- socket.end();
528
- return;
529
- }
572
+ if (node == null) {
573
+ // New CIRA connection for unknown node, disconnect.
574
+ unknownNodeCount++;
575
+ console.log('CIRA connection for unknown node. candidate(s): ' + nodes.length + ', groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
576
+ socket.end();
577
+ return;
578
+ }
579
531
- // Node is present
532
- if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
533
- socket.tag.nodeid = node._id;
534
- socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
535
- socket.tag.connectTime = Date.now();
536
-
537
- // Add the connection to the MPS connection list
538
- obj.ciraConnections[socket.tag.nodeid] = socket;
539
- delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
540
- SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
541
- });
542
- } else { // Unknown mesh type
543
- // New CIRA connection for unknown node, disconnect.
544
- unknownMeshIdCount++;
545
- console.log('CIRA connection to a unknown group type. groupid: ' + socket.tag.meshid);
546
- socket.end();
547
- return;
548
- }
549
- return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen;
580
+ // Node is present
581
+ if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
582
+ socket.tag.nodeid = node._id;
583
+ socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
584
+ socket.tag.connectTime = Date.now();
585
+
586
+ // Add the connection to the MPS connection list
587
+ obj.ciraConnections[socket.tag.nodeid] = socket;
588
+ delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
589
+ SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
590
+ });
591
+ } else { // Unknown mesh type
592
+ // New CIRA connection for unknown node, disconnect.
593
+ unknownMeshIdCount++;
594
+ console.log('CIRA connection to a unknown group type. groupid: ' + socket.tag.meshid);
595
+ socket.end();
596
+ return;
597
}
551
- case APFProtocol.SERVICE_REQUEST: {
552
- if (len < 5) return 0;
553
- var xserviceNameLen = common.ReadInt(data, 1);
554
- if (len < 5 + xserviceNameLen) return 0;
555
- var xserviceName = data.substring(5, 5 + xserviceNameLen);
556
- parent.debug('mpscmd', '--> SERVICE_REQUEST', xserviceName);
557
- if (xserviceName == "pfwd@amt.intel.com") { SendServiceAccept(socket, "pfwd@amt.intel.com"); }
558
- if (xserviceName == "auth@amt.intel.com") { SendServiceAccept(socket, "auth@amt.intel.com"); }
559
- return 5 + xserviceNameLen;
598
+ return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen;
599
+ }
600
+ case APFProtocol.SERVICE_REQUEST: {
601
+ if (len < 5) return 0;
602
+ var xserviceNameLen = common.ReadInt(data, 1);
603
+ if (len < 5 + xserviceNameLen) return 0;
604
+ var xserviceName = data.substring(5, 5 + xserviceNameLen);
605
+ parent.debug('mpscmd', '--> SERVICE_REQUEST', xserviceName);
606
+ if (xserviceName == "pfwd@amt.intel.com") { SendServiceAccept(socket, "pfwd@amt.intel.com"); }
607
+ if (xserviceName == "auth@amt.intel.com") { SendServiceAccept(socket, "auth@amt.intel.com"); }
608
+ return 5 + xserviceNameLen;
609
+ }
610
+ case APFProtocol.GLOBAL_REQUEST: {
611
+ if (len < 14) return 0;
612
+ var requestLen = common.ReadInt(data, 1);
613
+ if (len < 14 + requestLen) return 0;
614
+ var request = data.substring(5, 5 + requestLen);
615
+ //var wantResponse = data.charCodeAt(5 + requestLen);
616
+
617
+ if (request == 'tcpip-forward') {
618
+ var addrLen = common.ReadInt(data, 6 + requestLen);
619
+ if (len < 14 + requestLen + addrLen) return 0;
620
+ var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
621
+ var port = common.ReadInt(data, 10 + requestLen + addrLen);
622
+ parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
623
+ ChangeHostname(socket, addr, socket.tag.SystemId);
624
+ if (socket.tag.boundPorts.indexOf(port) == -1) { socket.tag.boundPorts.push(port); }
625
+ SendTcpForwardSuccessReply(socket, port);
626
+ return 14 + requestLen + addrLen;
627
}
561
- case APFProtocol.GLOBAL_REQUEST: {
562
- if (len < 14) return 0;
563
- var requestLen = common.ReadInt(data, 1);
564
- if (len < 14 + requestLen) return 0;
565
- var request = data.substring(5, 5 + requestLen);
566
- //var wantResponse = data.charCodeAt(5 + requestLen);
567
-
568
- if (request == 'tcpip-forward') {
569
- var addrLen = common.ReadInt(data, 6 + requestLen);
570
- if (len < 14 + requestLen + addrLen) return 0;
571
- var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
572
- var port = common.ReadInt(data, 10 + requestLen + addrLen);
573
- parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
574
- ChangeHostname(socket, addr, socket.tag.SystemId);
575
- if (socket.tag.boundPorts.indexOf(port) == -1) { socket.tag.boundPorts.push(port); }
576
- SendTcpForwardSuccessReply(socket, port);
577
- return 14 + requestLen + addrLen;
578
- }
579
-
580
- if (request == 'cancel-tcpip-forward') {
581
- var addrLen = common.ReadInt(data, 6 + requestLen);
582
- if (len < 14 + requestLen + addrLen) return 0;
583
- var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
584
- var port = common.ReadInt(data, 10 + requestLen + addrLen);
585
- parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
586
- var portindex = socket.tag.boundPorts.indexOf(port);
587
- if (portindex >= 0) { socket.tag.boundPorts.splice(portindex, 1); }
588
- SendTcpForwardCancelReply(socket);
589
- return 14 + requestLen + addrLen;
590
- }
591
-
592
- if (request == 'udp-send-to@amt.intel.com') {
593
- var addrLen = common.ReadInt(data, 6 + requestLen);
594
- if (len < 26 + requestLen + addrLen) return 0;
595
- var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
596
- var port = common.ReadInt(data, 10 + requestLen + addrLen);
597
- var oaddrLen = common.ReadInt(data, 14 + requestLen + addrLen);
598
- if (len < 26 + requestLen + addrLen + oaddrLen) return 0;
599
- var oaddr = data.substring(18 + requestLen, 18 + requestLen + addrLen);
600
- var oport = common.ReadInt(data, 18 + requestLen + addrLen + oaddrLen);
601
- var datalen = common.ReadInt(data, 22 + requestLen + addrLen + oaddrLen);
602
- if (len < 26 + requestLen + addrLen + oaddrLen + datalen) return 0;
603
- parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port, oaddr + ':' + oport, datalen);
604
- // TODO
605
- return 26 + requestLen + addrLen + oaddrLen + datalen;
606
- }
628
608
- return 6 + requestLen;
629
+ if (request == 'cancel-tcpip-forward') {
630
+ var addrLen = common.ReadInt(data, 6 + requestLen);
631
+ if (len < 14 + requestLen + addrLen) return 0;
632
+ var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
633
+ var port = common.ReadInt(data, 10 + requestLen + addrLen);
634
+ parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
635
+ var portindex = socket.tag.boundPorts.indexOf(port);
636
+ if (portindex >= 0) { socket.tag.boundPorts.splice(portindex, 1); }
637
+ SendTcpForwardCancelReply(socket);
638
+ return 14 + requestLen + addrLen;
639
}
610
- case APFProtocol.CHANNEL_OPEN: {
611
- if (len < 33) return 0;
612
- var ChannelTypeLength = common.ReadInt(data, 1);
613
- if (len < (33 + ChannelTypeLength)) return 0;
614
-
615
- // Decode channel identifiers and window size
616
- var ChannelType = data.substring(5, 5 + ChannelTypeLength);
617
- var SenderChannel = common.ReadInt(data, 5 + ChannelTypeLength);
618
- var WindowSize = common.ReadInt(data, 9 + ChannelTypeLength);
619
-
620
- // Decode the target
621
- var TargetLen = common.ReadInt(data, 17 + ChannelTypeLength);
622
- if (len < (33 + ChannelTypeLength + TargetLen)) return 0;
623
- var Target = data.substring(21 + ChannelTypeLength, 21 + ChannelTypeLength + TargetLen);
624
- var TargetPort = common.ReadInt(data, 21 + ChannelTypeLength + TargetLen);
625
-
626
- // Decode the source
627
- var SourceLen = common.ReadInt(data, 25 + ChannelTypeLength + TargetLen);
628
- if (len < (33 + ChannelTypeLength + TargetLen + SourceLen)) return 0;
629
- var Source = data.substring(29 + ChannelTypeLength + TargetLen, 29 + ChannelTypeLength + TargetLen + SourceLen);
630
- var SourcePort = common.ReadInt(data, 29 + ChannelTypeLength + TargetLen + SourceLen);
631
-
632
- channelOpenCount++;
633
- parent.debug('mpscmd', '--> CHANNEL_OPEN', ChannelType, SenderChannel, WindowSize, Target + ':' + TargetPort, Source + ':' + SourcePort);
634
-
635
- // Check if we understand this channel type
636
- //if (ChannelType.toLowerCase() == "direct-tcpip")
637
- {
638
- // We don't understand this channel type, send an error back
639
- SendChannelOpenFailure(socket, SenderChannel, APFChannelOpenFailureReasonCode.UnknownChannelType);
640
- return 33 + ChannelTypeLength + TargetLen + SourceLen;
641
- }
640
643
- /*
644
- // This is a correct connection. Lets get it setup
645
- var MeshAmtEventEndpoint = { ServerChannel: GetNextBindId(), AmtChannel: SenderChannel, MaxWindowSize: 2048, CurrentWindowSize:2048, SendWindow: WindowSize, InfoHeader: "Target: " + Target + ":" + TargetPort + ", Source: " + Source + ":" + SourcePort};
646
- // TODO: Connect this socket for a WSMAN event
647
- SendChannelOpenConfirmation(socket, SenderChannel, MeshAmtEventEndpoint.ServerChannel, MeshAmtEventEndpoint.MaxWindowSize);
648
- */
641
+ if (request == 'udp-send-to@amt.intel.com') {
642
+ var addrLen = common.ReadInt(data, 6 + requestLen);
643
+ if (len < 26 + requestLen + addrLen) return 0;
644
+ var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
645
+ var port = common.ReadInt(data, 10 + requestLen + addrLen);
646
+ var oaddrLen = common.ReadInt(data, 14 + requestLen + addrLen);
647
+ if (len < 26 + requestLen + addrLen + oaddrLen) return 0;
648
+ var oaddr = data.substring(18 + requestLen, 18 + requestLen + addrLen);
649
+ var oport = common.ReadInt(data, 18 + requestLen + addrLen + oaddrLen);
650
+ var datalen = common.ReadInt(data, 22 + requestLen + addrLen + oaddrLen);
651
+ if (len < 26 + requestLen + addrLen + oaddrLen + datalen) return 0;
652
+ parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port, oaddr + ':' + oport, datalen);
653
+ // TODO
654
+ return 26 + requestLen + addrLen + oaddrLen + datalen;
655
+ }
656
657
+ return 6 + requestLen;
658
+ }
659
+ case APFProtocol.CHANNEL_OPEN: {
660
+ if (len < 33) return 0;
661
+ var ChannelTypeLength = common.ReadInt(data, 1);
662
+ if (len < (33 + ChannelTypeLength)) return 0;
663
+
664
+ // Decode channel identifiers and window size
665
+ var ChannelType = data.substring(5, 5 + ChannelTypeLength);
666
+ var SenderChannel = common.ReadInt(data, 5 + ChannelTypeLength);
667
+ var WindowSize = common.ReadInt(data, 9 + ChannelTypeLength);
668
+
669
+ // Decode the target
670
+ var TargetLen = common.ReadInt(data, 17 + ChannelTypeLength);
671
+ if (len < (33 + ChannelTypeLength + TargetLen)) return 0;
672
+ var Target = data.substring(21 + ChannelTypeLength, 21 + ChannelTypeLength + TargetLen);
673
+ var TargetPort = common.ReadInt(data, 21 + ChannelTypeLength + TargetLen);
674
+
675
+ // Decode the source
676
+ var SourceLen = common.ReadInt(data, 25 + ChannelTypeLength + TargetLen);
677
+ if (len < (33 + ChannelTypeLength + TargetLen + SourceLen)) return 0;
678
+ var Source = data.substring(29 + ChannelTypeLength + TargetLen, 29 + ChannelTypeLength + TargetLen + SourceLen);
679
+ var SourcePort = common.ReadInt(data, 29 + ChannelTypeLength + TargetLen + SourceLen);
680
+
681
+ channelOpenCount++;
682
+ parent.debug('mpscmd', '--> CHANNEL_OPEN', ChannelType, SenderChannel, WindowSize, Target + ':' + TargetPort, Source + ':' + SourcePort);
683
+
684
+ // Check if we understand this channel type
685
+ //if (ChannelType.toLowerCase() == "direct-tcpip")
686
+ {
687
+ // We don't understand this channel type, send an error back
688
+ SendChannelOpenFailure(socket, SenderChannel, APFChannelOpenFailureReasonCode.UnknownChannelType);
689
return 33 + ChannelTypeLength + TargetLen + SourceLen;
690
}
652
- case APFProtocol.CHANNEL_OPEN_CONFIRMATION:
653
- {
654
- if (len < 17) return 0;
655
- var RecipientChannel = common.ReadInt(data, 1);
656
- var SenderChannel = common.ReadInt(data, 5);
657
- var WindowSize = common.ReadInt(data, 9);
658
- socket.tag.activetunnels++;
659
- var cirachannel = socket.tag.channels[RecipientChannel];
660
- if (cirachannel == null) { /*console.log("MPS Error in CHANNEL_OPEN_CONFIRMATION: Unable to find channelid " + RecipientChannel);*/ return 17; }
661
- cirachannel.amtchannelid = SenderChannel;
662
- cirachannel.sendcredits = cirachannel.amtCiraWindow = WindowSize;
663
- channelOpenConfirmCount++;
664
- parent.debug('mpscmd', '--> CHANNEL_OPEN_CONFIRMATION', RecipientChannel, SenderChannel, WindowSize);
665
- if (cirachannel.closing == 1) {
666
- // Close this channel
667
- SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
668
- } else {
669
- cirachannel.state = 2;
670
- // Send any pending data
671
- if (cirachannel.sendBuffer != null) {
672
- if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
673
- // Send the entire pending buffer
674
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
675
- cirachannel.sendcredits -= cirachannel.sendBuffer.length;
676
- delete cirachannel.sendBuffer;
677
- if (cirachannel.onSendOk) { cirachannel.onSendOk(cirachannel); }
678
- } else {
679
- // Send a part of the pending buffer
680
- SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer.substring(0, cirachannel.sendcredits));
681
- cirachannel.sendBuffer = cirachannel.sendBuffer.substring(cirachannel.sendcredits);
682
- cirachannel.sendcredits = 0;
683
- }
684
- }
685
- // Indicate the channel is open
686
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
687
- }
688
- return 17;
689
- }
690
- case APFProtocol.CHANNEL_OPEN_FAILURE:
691
- {
692
- if (len < 17) return 0;
693
- var RecipientChannel = common.ReadInt(data, 1);
694
- var ReasonCode = common.ReadInt(data, 5);
695
- channelOpenFailCount++;
696
- parent.debug('mpscmd', '--> CHANNEL_OPEN_FAILURE', RecipientChannel, ReasonCode);
697
- var cirachannel = socket.tag.channels[RecipientChannel];
698
- if (cirachannel == null) { console.log("MPS Error in CHANNEL_OPEN_FAILURE: Unable to find channelid " + RecipientChannel); return 17; }
699
- if (cirachannel.state > 0) {
700
- cirachannel.state = 0;
701
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
702
- delete socket.tag.channels[RecipientChannel];
703
- }
704
- return 17;
705
- }
706
- case APFProtocol.CHANNEL_CLOSE:
707
- {
708
- if (len < 5) return 0;
709
- var RecipientChannel = common.ReadInt(data, 1);
710
- channelCloseCount++;
711
- parent.debug('mpscmd', '--> CHANNEL_CLOSE', RecipientChannel);
712
- var cirachannel = socket.tag.channels[RecipientChannel];
713
- if (cirachannel == null) { console.log("MPS Error in CHANNEL_CLOSE: Unable to find channelid " + RecipientChannel); return 5; }
714
- socket.tag.activetunnels--;
715
- if (cirachannel.state > 0) {
716
- cirachannel.state = 0;
717
- if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
718
- SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
719
- delete socket.tag.channels[RecipientChannel];
720
- }
721
- return 5;
722
- }
723
- case APFProtocol.CHANNEL_WINDOW_ADJUST:
724
- {
725
- if (len < 9) return 0;
726
- var RecipientChannel = common.ReadInt(data, 1);
727
- var ByteToAdd = common.ReadInt(data, 5);
728
- var cirachannel = socket.tag.channels[RecipientChannel];
729
- if (cirachannel == null) { console.log("MPS Error in CHANNEL_WINDOW_ADJUST: Unable to find channelid " + RecipientChannel); return 9; }
730
- cirachannel.sendcredits += ByteToAdd;
731
- parent.debug('mpscmd', '--> CHANNEL_WINDOW_ADJUST', RecipientChannel, ByteToAdd, cirachannel.sendcredits);
732
- if (cirachannel.state == 2 && cirachannel.sendBuffer != null) {
733
- // Compute how much data we can send
691
+
692
+ /*
693
+ // This is a correct connection. Lets get it setup
694
+ var MeshAmtEventEndpoint = { ServerChannel: GetNextBindId(), AmtChannel: SenderChannel, MaxWindowSize: 2048, CurrentWindowSize:2048, SendWindow: WindowSize, InfoHeader: "Target: " + Target + ":" + TargetPort + ", Source: " + Source + ":" + SourcePort};
695
+ // TODO: Connect this socket for a WSMAN event
696
+ SendChannelOpenConfirmation(socket, SenderChannel, MeshAmtEventEndpoint.ServerChannel, MeshAmtEventEndpoint.MaxWindowSize);
697
+ */
698
+
699
+ return 33 + ChannelTypeLength + TargetLen + SourceLen;
700
+ }
701
+ case APFProtocol.CHANNEL_OPEN_CONFIRMATION:
702
+ {
703
+ if (len < 17) return 0;
704
+ var RecipientChannel = common.ReadInt(data, 1);
705
+ var SenderChannel = common.ReadInt(data, 5);
706
+ var WindowSize = common.ReadInt(data, 9);
707
+ socket.tag.activetunnels++;
708
+ var cirachannel = socket.tag.channels[RecipientChannel];
709
+ if (cirachannel == null) { /*console.log("MPS Error in CHANNEL_OPEN_CONFIRMATION: Unable to find channelid " + RecipientChannel);*/ return 17; }
710
+ cirachannel.amtchannelid = SenderChannel;
711
+ cirachannel.sendcredits = cirachannel.amtCiraWindow = WindowSize;
712
+ channelOpenConfirmCount++;
713
+ parent.debug('mpscmd', '--> CHANNEL_OPEN_CONFIRMATION', RecipientChannel, SenderChannel, WindowSize);
714
+ if (cirachannel.closing == 1) {
715
+ // Close this channel
716
+ SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
717
+ } else {
718
+ cirachannel.state = 2;
719
+ // Send any pending data
720
+ if (cirachannel.sendBuffer != null) {
721
if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
722
// Send the entire pending buffer
723
SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
@@ -744,63 +731,110 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
731
cirachannel.sendcredits = 0;
732
}
733
}
747
- return 9;
734
+ // Indicate the channel is open
735
+ if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
736
}
749
- case APFProtocol.CHANNEL_DATA:
750
- {
751
- if (len < 9) return 0;
752
- var RecipientChannel = common.ReadInt(data, 1);
753
- var LengthOfData = common.ReadInt(data, 5);
754
- if (len < (9 + LengthOfData)) return 0;
755
- parent.debug('mpscmddata', '--> CHANNEL_DATA', RecipientChannel, LengthOfData);
756
- var cirachannel = socket.tag.channels[RecipientChannel];
757
- if (cirachannel == null) { console.log("MPS Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return 9 + LengthOfData; }
758
- cirachannel.amtpendingcredits += LengthOfData;
759
- if (cirachannel.onData) cirachannel.onData(cirachannel, data.substring(9, 9 + LengthOfData));
760
- if (cirachannel.amtpendingcredits > (cirachannel.ciraWindow / 2)) {
761
- SendChannelWindowAdjust(cirachannel.socket, cirachannel.amtchannelid, cirachannel.amtpendingcredits); // Adjust the buffer window
762
- cirachannel.amtpendingcredits = 0;
763
- }
764
- return 9 + LengthOfData;
737
+ return 17;
738
+ }
739
+ case APFProtocol.CHANNEL_OPEN_FAILURE:
740
+ {
741
+ if (len < 17) return 0;
742
+ var RecipientChannel = common.ReadInt(data, 1);
743
+ var ReasonCode = common.ReadInt(data, 5);
744
+ channelOpenFailCount++;
745
+ parent.debug('mpscmd', '--> CHANNEL_OPEN_FAILURE', RecipientChannel, ReasonCode);
746
+ var cirachannel = socket.tag.channels[RecipientChannel];
747
+ if (cirachannel == null) { console.log("MPS Error in CHANNEL_OPEN_FAILURE: Unable to find channelid " + RecipientChannel); return 17; }
748
+ if (cirachannel.state > 0) {
749
+ cirachannel.state = 0;
750
+ if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
751
+ delete socket.tag.channels[RecipientChannel];
752
}
766
- case APFProtocol.DISCONNECT:
767
- {
768
- if (len < 7) return 0;
769
- var ReasonCode = common.ReadInt(data, 1);
770
- disconnectCommandCount++;
771
- parent.debug('mpscmd', '--> DISCONNECT', ReasonCode);
772
- try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
773
- obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
774
- return 7;
753
+ return 17;
754
+ }
755
+ case APFProtocol.CHANNEL_CLOSE:
756
+ {
757
+ if (len < 5) return 0;
758
+ var RecipientChannel = common.ReadInt(data, 1);
759
+ channelCloseCount++;
760
+ parent.debug('mpscmd', '--> CHANNEL_CLOSE', RecipientChannel);
761
+ var cirachannel = socket.tag.channels[RecipientChannel];
762
+ if (cirachannel == null) { console.log("MPS Error in CHANNEL_CLOSE: Unable to find channelid " + RecipientChannel); return 5; }
763
+ socket.tag.activetunnels--;
764
+ if (cirachannel.state > 0) {
765
+ cirachannel.state = 0;
766
+ if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
767
+ SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
768
+ delete socket.tag.channels[RecipientChannel];
769
+ }
770
+ return 5;
771
+ }
772
+ case APFProtocol.CHANNEL_WINDOW_ADJUST:
773
+ {
774
+ if (len < 9) return 0;
775
+ var RecipientChannel = common.ReadInt(data, 1);
776
+ var ByteToAdd = common.ReadInt(data, 5);
777
+ var cirachannel = socket.tag.channels[RecipientChannel];
778
+ if (cirachannel == null) { console.log("MPS Error in CHANNEL_WINDOW_ADJUST: Unable to find channelid " + RecipientChannel); return 9; }
779
+ cirachannel.sendcredits += ByteToAdd;
780
+ parent.debug('mpscmd', '--> CHANNEL_WINDOW_ADJUST', RecipientChannel, ByteToAdd, cirachannel.sendcredits);
781
+ if (cirachannel.state == 2 && cirachannel.sendBuffer != null) {
782
+ // Compute how much data we can send
783
+ if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
784
+ // Send the entire pending buffer
785
+ SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
786
+ cirachannel.sendcredits -= cirachannel.sendBuffer.length;
787
+ delete cirachannel.sendBuffer;
788
+ if (cirachannel.onSendOk) { cirachannel.onSendOk(cirachannel); }
789
+ } else {
790
+ // Send a part of the pending buffer
791
+ SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer.substring(0, cirachannel.sendcredits));
792
+ cirachannel.sendBuffer = cirachannel.sendBuffer.substring(cirachannel.sendcredits);
793
+ cirachannel.sendcredits = 0;
794
+ }
795
}
776
- default:
777
- {
778
- parent.debug('mpscmd', '--> Unknown CIRA command: ' + cmd);
779
- return -1;
796
+ return 9;
797
+ }
798
+ case APFProtocol.CHANNEL_DATA:
799
+ {
800
+ if (len < 9) return 0;
801
+ var RecipientChannel = common.ReadInt(data, 1);
802
+ var LengthOfData = common.ReadInt(data, 5);
803
+ if (len < (9 + LengthOfData)) return 0;
804
+ parent.debug('mpscmddata', '--> CHANNEL_DATA', RecipientChannel, LengthOfData);
805
+ var cirachannel = socket.tag.channels[RecipientChannel];
806
+ if (cirachannel == null) { console.log("MPS Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return 9 + LengthOfData; }
807
+ cirachannel.amtpendingcredits += LengthOfData;
808
+ if (cirachannel.onData) cirachannel.onData(cirachannel, data.substring(9, 9 + LengthOfData));
809
+ if (cirachannel.amtpendingcredits > (cirachannel.ciraWindow / 2)) {
810
+ SendChannelWindowAdjust(cirachannel.socket, cirachannel.amtchannelid, cirachannel.amtpendingcredits); // Adjust the buffer window
811
+ cirachannel.amtpendingcredits = 0;
812
}
781
- }
813
+ return 9 + LengthOfData;
814
+ }
815
+ case APFProtocol.DISCONNECT:
816
+ {
817
+ if (len < 7) return 0;
818
+ var ReasonCode = common.ReadInt(data, 1);
819
+ disconnectCommandCount++;
820
+ parent.debug('mpscmd', '--> DISCONNECT', ReasonCode);
821
+ try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
822
+ obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connType);
823
+ return 7;
824
+ }
825
+ default:
826
+ {
827
+ parent.debug('mpscmd', '--> Unknown CIRA command: ' + cmd);
828
+ return -1;
829
+ }
830
}
783
-
784
- socket.addListener('close', function () {
785
- socketClosedCount++;
786
- parent.debug('mps', 'CIRA connection closed');
787
- try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
788
- obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
789
- });
790
-
791
- socket.addListener('error', function () {
792
- socketErrorCount++;
793
- parent.debug('mps', 'CIRA connection error');
794
- //console.log("MPS Error: " + socket.remoteAddress);
795
- });
796
-
831
}
832
833
// Disconnect CIRA tunnel
834
obj.close = function (socket) {
835
try { socket.end(); } catch (e) { }
836
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
803
- obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
837
+ obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connType);
838
};
839
840
function SendServiceAccept(socket, service) {
@@ -886,9 +920,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
920
// Print out sent bytes
921
var buf = Buffer.from(data, 'binary');
922
console.log('MPS <-- (' + buf.length + '):' + buf.toString('hex'));
889
- socket.write(buf);
923
+ if (socket.websocket == 1) { socket.send(buf); } else { socket.write(buf); }
924
} else {
891
- socket.write(Buffer.from(data, 'binary'));
925
+ if (socket.websocket == 1) { socket.send(Buffer.from(data, 'binary')); } else { socket.write(Buffer.from(data, 'binary')); }
926
}
927
}
928
webserver.js
+1
-1
@@ -4846,7 +4846,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4846
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
4847
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
4848
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
4849
- obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.apfserver.onConnection(ws); })
4849
+ obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.mpsserver.onWebSocketConnection(ws); })
4850
obj.app.get(url + 'webrelay.ashx', function (req, res) { res.send('Websocket connection expected'); });
4851
obj.app.get(url + 'health.ashx', function (req, res) { res.send('ok'); }); // TODO: Perform more server checking.
4852
obj.app.ws(url + 'webrelay.ashx', function (ws, req) { PerformWSSessionAuth(ws, req, false, handleRelayWebSocket); });