First version with CIRA support in AMT Manager.

Ylian Saint-Hilaire committed Oct 8, 2020 at 12:50 UTC 88b38f9c324a2175485a6be56f7c0ff6418b7227
6 files changed +81 -24
amt/amt-redir-mesh.js
+2 -2
@@ -126,7 +126,7 @@ module.exports.CreateAmtRedirect = function (module, domain, user, webserver, me
126 if ((port == 16993) || (port == 16995)) {
127 // Perform TLS - ( TODO: THIS IS BROKEN on Intel AMT v7 but works on v10, Not sure why. Well, could be broken TLS 1.0 in firmware )
128 var ser = new SerialTunnel();
129 - var chnl = meshcentral.mpsserver.SetupCiraChannel(ciraconn, port);
129 + var chnl = meshcentral.mpsserver.SetupChannel(ciraconn, port);
130
131 // let's chain up the TLSSocket <-> SerialTunnel <-> CIRA APF (chnl)
132 // Anything that needs to be forwarded by SerialTunnel will be encapsulated by chnl write
@@ -171,7 +171,7 @@ module.exports.CreateAmtRedirect = function (module, domain, user, webserver, me
171 obj.forwardclient.xtls = 1;
172 } else {
173 // Without TLS
174 - obj.forwardclient = meshcentral.mpsserver.SetupCiraChannel(ciraconn, port);
174 + obj.forwardclient = meshcentral.mpsserver.SetupChannel(ciraconn, port);
175 obj.forwardclient.xtls = 0;
176 }
177
amt/amt-wsman-comm.js
+2 -2
@@ -167,8 +167,8 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, transpo
167 obj.kerberosDone = 0;
168
169 if (obj.transportServer != null) {
170 - // CIRA or APF server
171 - obj.socket = obj.transportServer.SetupCiraChannelToHost(obj.host, obj.port);
170 + // Setup a new channel using the transport server (CIRA or APF)
171 + obj.socket = obj.transportServer.SetupChannelToNode(obj.host, obj.port);
172 if (obj.socket == null) {
173 try { obj.xxOnSocketClosed(); } catch (e) { }
174 } else {
amtmanager.js
+47 -4
@@ -44,15 +44,19 @@ 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 *****************************
48 +
49 // We have an OOB connection to Intel AMT, update our information
50 var dev = obj.amtDevices[event.nodeid];
51 if (dev == null) { obj.amtDevices[event.nodeid] = dev = { conn: event.conn }; fetchIntelAmtInformation(event.nodeid); } else { dev.conn = event.conn; }
52 + /*
53 } else if (((event.conn & 1) != 0) && (parent.webserver != null)) {
54 // We have an agent connection without OOB, check if this agent supports Intel AMT
55 var agent = parent.webserver.wsagents[event.nodeid];
56 if ((agent == null) || (agent.agentInfo == null) || (parent.meshAgentsArchitectureNumbers[agent.agentInfo.agentId].amt == false)) { removeDevice(event.nodeid); return; }
57 var dev = obj.amtDevices[event.nodeid];
58 if (dev == null) { obj.amtDevices[event.nodeid] = dev = { conn: event.conn }; fetchIntelAmtInformation(event.nodeid); } else { dev.conn = event.conn; }
59 + */
60 } else {
61 removeDevice(event.nodeid);
62 }
@@ -195,6 +199,42 @@ module.exports.CreateAmtManager = function(parent) {
199 if (obj.amtAdminAccounts.length > 0) { dev.acctry = 0; } else { return; }
200 }
201
202 + // Handle the case where the Intel AMT CIRA is connected (conn & 2)
203 + if ((dev.conn & 2) != 0) {
204 + // Check to see if CIRA is connected on this server.
205 + var ciraconn = parent.mpsserver.ciraConnections[dev.nodeid];
206 + if ((ciraconn == null) || (ciraconn.tag == null) || (ciraconn.tag.boundPorts == null)) { removeDevice(dev.nodeid); return; } // CIRA connection is not on this server, no need to deal with this device anymore.
207 +
208 + // See what user/pass to try.
209 + var user = null, pass = null;
210 + if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; } else { user = obj.amtAdminAccounts[dev.acctry].user; pass = obj.amtAdminAccounts[dev.acctry].pass; }
211 +
212 + // See if we need to perform TLS or not. We prefer not to do TLS within CIRA.
213 + var dotls = -1;
214 + if (ciraconn.tag.boundPorts.indexOf('16992')) { dotls = 0; }
215 + else if (ciraconn.tag.boundPorts.indexOf('16993')) { dotls = 1; }
216 + if (dotls == -1) { removeDevice(dev.nodeid); return; } // The Intel AMT ports are not open, not a device we can deal with.
217 +
218 + // Connect now
219 + console.log('CIRA-Connect', (dotls == 1)?"TLS":"NoTLS", dev.name, dev.host, user, pass);
220 + var comm;
221 + if (dotls == 1) {
222 + comm = CreateWsmanComm(dev.nodeid, 16993, user, pass, 1, null, parent.mpsserver); // Perform TLS
223 + comm.xtlsFingerprint = 0; // Perform no certificate checking
224 + } else {
225 + comm = CreateWsmanComm(dev.nodeid, 16992, user, pass, 0, null, parent.mpsserver); // No TLS
226 + }
227 + var wsstack = WsmanStackCreateService(comm);
228 + dev.amtstack = AmtStackCreateService(wsstack);
229 + dev.amtstack.dev = dev;
230 + obj.activeLocalConnections[dev.host] = dev;
231 + dev.amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], attemptLocalConnectResponse);
232 + dev.conntype = 2; // CIRA
233 +
234 + return; // If CIRA is connected, don't try any other methods.
235 + }
236 +
237 + // Handle the case where the Intel AMT local scanner found the device (conn & 4)
238 if (((dev.conn & 4) != 0) && (typeof dev.host == 'string')) {
239 // Since we don't allow two or more connections to the same host, check if a pending connection is active.
240 if (obj.activeLocalConnections[dev.host] != null) {
@@ -218,12 +258,15 @@ module.exports.CreateAmtManager = function(parent) {
258 dev.amtstack = AmtStackCreateService(wsstack);
259 dev.amtstack.dev = dev;
260 obj.activeLocalConnections[dev.host] = dev;
221 - dev.amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], attemptLocalConectResponse);
261 + dev.amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], attemptLocalConnectResponse);
262 + dev.conntype = 1; // LOCAL
263 }
264 }
265 }
266
226 - function attemptLocalConectResponse(stack, name, responses, status) {
267 + function attemptLocalConnectResponse(stack, name, responses, status) {
268 + console.log('attemptLocalConnectResponse', status);
269 +
270 // Release active connection to this host.
271 delete obj.activeLocalConnections[stack.wsman.comm.host];
272
@@ -255,8 +298,8 @@ module.exports.CreateAmtManager = function(parent) {
298 fetchPowerState(dev);
299 } else {
300 // We got a bad response
258 - if ((dev.tlsfail !== true) && (status == 408)) {
259 - // TLS error, try again without TLS
301 + if ((dev.conntype == 1) && (dev.tlsfail !== true) && (status == 408)) {
302 + // TLS error on a local connection, try again without TLS
303 dev.tlsfail = true; attemptInitialContact(dev.nodeid, dev); return;
304 } else if (status == 401) {
305 // Authentication error, see if we can use alternative credentials
apfserver.js
+5 -4
@@ -641,13 +641,14 @@ module.exports.CreateApfServer = function (parent, db, args) {
641 }
642 }
643
644 - obj.SetupCiraChannelToHost = function (host, targetport) {
645 - var apfconn = obj.apfConnections[host];
644 + // Setup a new channel to a nodeid
645 + obj.SetupChannelToNode = function (nodeid, targetport) {
646 + var apfconn = obj.apfConnections[nodeid];
647 if (apfconn == null) return null;
647 - return obj.SetupCiraChannel(apfconn, targetport);
648 + return obj.SetupChannel(apfconn, targetport);
649 }
650
650 - obj.SetupCiraChannel = function (socket, targetport) {
651 + obj.SetupChannel = function (socket, targetport) {
652 var sourceport = (socket.tag.nextsourceport++ % 30000) + 1024;
653 var cirachannel = { targetport: targetport, channelid: socket.tag.nextchannelid++, socket: socket, state: 1, sendcredits: 0, amtpendingcredits: 0, amtCiraWindow: 0, ciraWindow: 32768 };
654 SendChannelOpen(socket, false, cirachannel.channelid, cirachannel.ciraWindow, socket.tag.host, targetport, "1.2.3.4", sourceport);
mpsserver.js
+23 -10
@@ -142,6 +142,16 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
142 var socketErrorCount = 0;
143 var maxDomainDevicesReached = 0;
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); } }
149 + f.nodeid = nodeid;
150 + f.meshid = meshid;
151 + f.connectTime = connectTime;
152 + setTimeout(f, 300);
153 + }
154 +
155 // Return statistics about this MPS server
156 obj.getStats = function () {
157 return {
@@ -324,7 +334,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
334
335 // Add the connection to the MPS connection list
336 obj.ciraConnections[socket.tag.nodeid] = socket;
327 - 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.
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);
339 }
340 });
341 return;
@@ -354,7 +365,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
365
366 // Add the connection to the MPS connection list
367 obj.ciraConnections[socket.tag.nodeid] = socket;
357 - 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.
368 + delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
369 });
370 } else {
371 // This node connected without certificate authentication, use password auth
@@ -372,7 +383,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
383 }
384 });
385
375 - // Process one AFP command
386 + // Process one APF command
387 function ProcessCommand(socket) {
388 var cmd = socket.tag.accumulator.charCodeAt(0);
389 var len = socket.tag.accumulator.length;
@@ -462,7 +473,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
473
474 // Add the connection to the MPS connection list
475 obj.ciraConnections[socket.tag.nodeid] = socket;
465 - 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.
476 + delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
477 SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
478 }
479 });
@@ -486,7 +497,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
497
498 // Add the connection to the MPS connection list
499 obj.ciraConnections[socket.tag.nodeid] = socket;
489 - 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.
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
@@ -525,7 +536,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
536
537 // Add the connection to the MPS connection list
538 obj.ciraConnections[socket.tag.nodeid] = socket;
528 - 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.
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
@@ -866,13 +877,15 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
877 }
878 }
879
869 - obj.SetupCiraChannelToHost = function (host, targetport) {
870 - var ciraconn = obj.ciraConnections[host];
880 + // Setup a new channel to a nodeid
881 + obj.SetupChannelToNode = function (nodeid, targetport) {
882 + var ciraconn = obj.ciraConnections[nodeid];
883 if (ciraconn == null) return null;
872 - return obj.SetupCiraChannel(ciraconn, targetport);
884 + return obj.SetupChannel(ciraconn, targetport);
885 }
886
875 - obj.SetupCiraChannel = function (socket, targetport) {
887 + // Setup a new channel
888 + obj.SetupChannel = function (socket, targetport) {
889 var sourceport = (socket.tag.nextsourceport++ % 30000) + 1024;
890 var cirachannel = { targetport: targetport, channelid: socket.tag.nextchannelid++, socket: socket, state: 1, sendcredits: 0, amtpendingcredits: 0, amtCiraWindow: 0, ciraWindow: 32768 };
891 SendChannelOpen(socket, false, cirachannel.channelid, cirachannel.ciraWindow, socket.tag.host, targetport, "1.2.3.4", sourceport);
webserver.js
+2 -2
@@ -3390,7 +3390,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3390 if ((port == 16993) || (port == 16995)) {
3391 // Perform TLS - ( TODO: THIS IS BROKEN on Intel AMT v7 but works on v10, Not sure why. Well, could be broken TLS 1.0 in firmware )
3392 var ser = new SerialTunnel();
3393 - var chnl = parent.mpsserver.SetupCiraChannel(ciraconn, port);
3393 + var chnl = parent.mpsserver.SetupChannel(ciraconn, port);
3394
3395 // Let's chain up the TLSSocket <-> SerialTunnel <-> CIRA APF (chnl)
3396 // Anything that needs to be forwarded by SerialTunnel will be encapsulated by chnl write
@@ -3436,7 +3436,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3436 ws.forwardclient.xtls = 1;
3437 } else {
3438 // Without TLS
3439 - ws.forwardclient = parent.mpsserver.SetupCiraChannel(ciraconn, port);
3439 + ws.forwardclient = parent.mpsserver.SetupChannel(ciraconn, port);
3440 ws.forwardclient.xtls = 0;
3441 ws._socket.resume();
3442 }