Completed Intel AMT CCM deactivation support.

Ylian Saint-Hilaire committed Oct 21, 2020 at 12:19 UTC 2aacb65efb75e7c2e4b3082e1d6d205bfb7dafca
8 files changed +124 -17
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/meshcmd.js
+6
@@ -1183,6 +1183,12 @@ function configureJsonControl(data) {
1183 case 'mestate': // Request an updated MEI state
1184 getMeiState(15, function (state) { settings.apftunnel.updateMeiState(state); });
1185 break;
1186 + case 'deactivate': // Request CCM deactivation
1187 + var amtMeiModule, amtMei;
1188 + try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { settings.apftunnel.sendMeiDeactivationState(1); break; }
1189 + amtMei.on('error', function (e) { settings.apftunnel.sendMeiDeactivationState(1); });
1190 + amtMei.unprovision(1, function (status) { settings.apftunnel.sendMeiDeactivationState(status); }); // 0 = Success
1191 + break;
1192 case 'close': // Close the CIRA-LMS connection
1193 exit(0);
1194 break;
agents/meshcore.js
+6
@@ -3564,6 +3564,12 @@ function createMeshCore(agent) {
3564 apftunnel.onJsonControl = function (data) {
3565 if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); } // Display a console message
3566 if (data.action == 'mestate') { getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
3567 + if (data.action == 'deactivate') { // Request CCM deactivation
3568 + var amtMeiModule, amtMei;
3569 + try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { apftunnel.sendMeiDeactivationState(1); break; }
3570 + amtMei.on('error', function (e) { apftunnel.sendMeiDeactivationState(1); });
3571 + amtMei.unprovision(1, function (status) { apftunnel.sendMeiDeactivationState(status); }); // 0 = Success
3572 + }
3573 if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; } // Close the CIRA-LMS connection
3574 }
3575 apftunnel.onChannelClosed = function () { apftunnel = null; }
agents/modules_meshcmd/apfclient.js
+1
@@ -182,6 +182,7 @@ function CreateAPFClient(parent, args) {
182 }
183
184 obj.updateMeiState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'meiState', value: state }); }
185 + obj.sendMeiDeactivationState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'deactivate', value: state }); }
186
187 function SendJsonControl(socket, o) {
188 var data = JSON.stringify(o)
agents/modules_meshcore/apfclient.js
+1
@@ -182,6 +182,7 @@ function CreateAPFClient(parent, args) {
182 }
183
184 obj.updateMeiState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'meiState', value: state }); }
185 + obj.sendMeiDeactivationState = function (state) { SendJsonControl(obj.forwardClient.ws, { action: 'deactivate', value: state }); }
186
187 function SendJsonControl(socket, o) {
188 var data = JSON.stringify(o)
amtmanager.js
+105 -15
@@ -168,6 +168,30 @@ module.exports.CreateAmtManager = function(parent) {
168 return r;
169 }
170
171 + // Receive a JSON control message from the MPS server
172 + obj.mpsControlMessage = function (nodeid, conn, connType, jsondata) {
173 + // Find the devices in the list
174 + var dev = null;
175 + var devices = obj.amtDevices[nodeid];
176 + if (devices == null) return;
177 + for (var i in devices) { if (devices[i].mpsConnection === conn) { dev = devices[i]; } }
178 + if (dev == null) return;
179 +
180 + // Process the message
181 + switch (jsondata.action) {
182 + case 'deactivate':
183 + if ((dev.connType != 2) || (dev.deactivateCcmPending != 1)) break; // Only accept MEI state on CIRA-LMS connection
184 + delete dev.deactivateCcmPending;
185 + deactivateIntelAmtCCMEx(dev, jsondata.value);
186 + break;
187 + case 'meiState':
188 + if (dev.pendingUpdatedMeiState != 1) break;
189 + delete dev.pendingUpdatedMeiState;
190 + attemptInitialContact(dev);
191 + break;
192 + }
193 + }
194 +
195 // Subscribe to server events
196 parent.AddEventDispatch(['*'], obj);
197
@@ -221,25 +245,62 @@ module.exports.CreateAmtManager = function(parent) {
245 const mesh = parent.webserver.meshes[node.meshid];
246 if (mesh == null) { removeAmtDevice(dev); return; }
247 if (dev == null) { return; }
248 +
249 + // Fetch Intel AMT setup policy
250 + // mesh.amt.type: 0 = No Policy, 1 = Deactivate CCM, 2 = Manage in CCM, 3 = Manage in ACM
251 + // mesh.amt.cirasetup: 0 = No Change, 1 = Remove CIRA, 2 = Setup CIRA
252 + var amtPolicy = 0, ciraPolicy = 0;
253 + if (mesh.amt != null) { if (mesh.amt.type) { amtPolicy = mesh.amt.type; } if (mesh.amt.cirasetup) { ciraPolicy = mesh.amt.cirasetup; } }
254 + if (amtPolicy < 2) { ciraPolicy = 0; }
255 + dev.policy = { amtPolicy: amtPolicy, ciraPolicy: ciraPolicy }
256 +
257 + // If there is no Intel AMT policy for this device, stop here.
258 + if (amtPolicy == 0) { dev.consoleMsg("Done."); removeAmtDevice(dev); return; }
259 +
260 + // Setup the monitored device
261 dev.name = node.name;
262 //if (node.host) { dev.host = node.host.toLowerCase(); }
263 dev.meshid = node.meshid;
264 dev.intelamt = node.intelamt;
228 - dev.consoleMsg("Attempting Intel AMT connection...");
265 + dev.consoleMsg("Checking Intel AMT state...");
266 attemptInitialContact(dev);
267 });
268 }
269
270 // Attempt to perform initial contact with Intel AMT
271 function attemptInitialContact(dev) {
272 + delete dev.amtstack; // If there is a WSMAn stack setup, clean it up now.
273 parent.debug('amt', "Attempt Initial Contact", dev.name, dev.connType);
274
237 - if ((dev.connType == 2) && (dev.mpsConnection != null) && (dev.mpsConnection.tag != null) && (dev.mpsConnection.tag.meiState != null) && (dev.mpsConnection.tag.meiState.ProvisioningState !== 2)) {
238 - // This Intel AMT device is not activated, we need to work on activating it.
239 - activateIntelAmt(dev);
240 - return;
275 + // Check Intel AMT policy when CIRA-LMS connection is in use.
276 + if ((dev.connType == 2) && (dev.mpsConnection != null) && (dev.mpsConnection.tag != null) && (dev.mpsConnection.tag.meiState != null)) {
277 + // Intel AMT activation policy
278 + if ((dev.policy.amtPolicy > 1) && (dev.mpsConnection.tag.meiState.ProvisioningState !== 2)) {
279 + // This Intel AMT device is not activated, we need to work on activating it.
280 + activateIntelAmt(dev);
281 + return;
282 + }
283 + // Intel AMT CCM deactivation policy
284 + if (dev.policy.amtPolicy == 1) {
285 + if ((dev.mpsConnection.tag.meiState.ProvisioningState == 2) && ((dev.mpsConnection.tag.meiState.Flags & 2) != 0)) {
286 + // Deactivate CCM.
287 + deactivateIntelAmtCCM(dev);
288 + } else {
289 + // Already deactivated or in ACM, do nothing.
290 + dev.consoleMsg("Done.");
291 + removeAmtDevice(dev);
292 + }
293 + return;
294 + }
295 + // No Intel AMT policy, stop here
296 + if (dev.policy.amtPolicy == 0) {
297 + dev.consoleMsg("Done.");
298 + removeAmtDevice(dev);
299 + return;
300 + }
301 }
302
303 + // If we ran out of credentials to try, give up here.
304 if ((dev.acctry == null) && ((typeof dev.intelamt.user != 'string') || (typeof dev.intelamt.pass != 'string'))) {
305 if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { removeAmtDevice(dev); return; }
306 }
@@ -368,14 +429,12 @@ module.exports.CreateAmtManager = function(parent) {
429 if (stack.wsman.comm.xtls == 1) { dev.aquired.hash = stack.wsman.comm.xtlsCertificate.fingerprint.split(':').join('').toLowerCase(); } else { delete dev.aquired.hash; }
430 UpdateDevice(dev);
431
371 - // TODO: Enable redirection port and KVM
372 -
432 // Perform Intel AMT clock sync
433 attemptSyncClock(dev, function (dev) {
434 // Check Intel AMT TLS state
435 attemptTlsSync(dev, function (dev) {
436 // If we need to switch to TLS, do it now.
378 - if (dev.switchToTls == 1) { delete dev.amtstack; delete dev.switchToTls; attemptInitialContact(dev); return; }
437 + if (dev.switchToTls == 1) { delete dev.switchToTls; attemptInitialContact(dev); return; }
438 // Check Intel AMT root certificate state
439 attemptRootCertSync(dev, function (dev) {
440 // Check Intel AMT CIRA settings
@@ -611,7 +670,6 @@ module.exports.CreateAmtManager = function(parent) {
670 dev.amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, attemptSyncClockSet);
671 } else {
672 // Clock is fine, we are done.
614 - dev.consoleMsg("Clock ok.");
673 devTaskCompleted(dev)
674 }
675 }
@@ -633,7 +691,7 @@ module.exports.CreateAmtManager = function(parent) {
691 function attemptTlsSync(dev, func) {
692 if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
693
636 - // Fetch Intel AMT setup policy
694 + // Refetch Intel AMT setup policy
695 // mesh.amt.type: 0 = No Policy, 1 = Deactivate CCM, 2 = Manage in CCM, 3 = Manage in ACM
696 // mesh.amt.cirasetup: 0 = No Change, 1 = Remove CIRA, 2 = Setup CIRA
697 const mesh = parent.webserver.meshes[dev.meshid];
@@ -1027,8 +1085,6 @@ module.exports.CreateAmtManager = function(parent) {
1085 dev.taskCount = 1;
1086 dev.taskCompleted = func;
1087
1030 - dev.consoleMsg("Checking settings...");
1031 -
1088 // Query the things we are going to be checking
1089 var query = ['*AMT_GeneralSettings', '*AMT_RedirectionService'];
1090 if (dev.aquired.majorver > 5) query.push('*CIM_KVMRedirectionSAP');
@@ -1080,7 +1136,7 @@ module.exports.CreateAmtManager = function(parent) {
1136 function (stack, name, response, status) {
1137 const dev = stack.dev;
1138 if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1083 - if (status == 200) { dev.consoleMsg("Enabled KVM"); }
1139 + if (status == 200) { dev.consoleMsg("Enabled KVM."); }
1140 devTaskCompleted(dev);
1141 }
1142 );
@@ -1350,12 +1406,46 @@ module.exports.CreateAmtManager = function(parent) {
1406
1407 // Success, switch to managing this device
1408 obj.parent.mpsserver.SendJsonControl(dev.mpsConnection, { action: 'mestate' }); // Request an MEI state refresh
1353 - dev.consoleMsg("Succesfully activated Intel AMT in CCM mode.");
1409 + dev.consoleMsg("Succesfully activated Intel AMT in CCM mode, holding 10 seconds...");
1410
1411 // Wait 8 seconds before attempting to manage this device in CCM
1412 var f = function doManage() { if (isAmtDeviceValid(dev)) { attemptInitialContact(doManage.dev); } }
1413 f.dev = dev;
1358 - setTimeout(f, 8000);
1414 + setTimeout(f, 10000);
1415 + }
1416 +
1417 +
1418 + //
1419 + // Intel AMT CCM deactivation
1420 + //
1421 +
1422 + function deactivateIntelAmtCCM(dev) {
1423 + dev.consoleMsg("Deactivating CCM...");
1424 + dev.deactivateCcmPending = 1;
1425 + dev.controlMsg({ action: 'deactivate' });
1426 + }
1427 +
1428 + // This is called after the deactivation call
1429 + function deactivateIntelAmtCCMEx(dev, state) {
1430 + if (state != 0) {
1431 + dev.consoleMsg("Failed to deactivate Intel AMT CCM.");
1432 + removeAmtDevice(dev);
1433 + } else {
1434 + if (dev.policy.amtPolicy == 1) { // CCM deactivation policy, we are done.
1435 + dev.consoleMsg("Deactivation successful.");
1436 + dev.consoleMsg("Done.");
1437 + removeAmtDevice(dev);
1438 + } else {
1439 + // Wait 20 seconds before attempting any operation on this device
1440 + dev.consoleMsg("Deactivation successful, holding for 20 seconds...");
1441 + var f = function askMeiState() {
1442 + askMeiState.dev.pendingUpdatedMeiState = 1;
1443 + askMeiState.dev.controlMsg({ action: 'mestate' });
1444 + }
1445 + f.dev = dev;
1446 + setTimeout(f, 20000);
1447 + }
1448 + }
1449 }
1450
1451 //
mpsserver.js
+5 -2
@@ -899,8 +899,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
899 case 'meiState':
900 if (socket.tag.connType != 2) break; // Only accept MEI state on CIRA-LMS connection
901 socket.tag.meiState = jsondata.value;
902 - //if (socket.tag.meiState.UUID != null) { console.log('MEI State', socket.tag.meiState.UUID); }
903 - //console.log('meiState', JSON.stringify(socket.tag.meiState, null, 2)); // DEBUG
902 + if (obj.parent.amtManager != null) { obj.parent.amtManager.mpsControlMessage(socket.tag.nodeid, socket, socket.tag.connType, jsondata); }
903 + break;
904 + case 'deactivate':
905 + if (socket.tag.connType != 2) break; // Only accept MEI state on CIRA-LMS connection
906 + if (obj.parent.amtManager != null) { obj.parent.amtManager.mpsControlMessage(socket.tag.nodeid, socket, socket.tag.connType, jsondata); }
907 break;
908 }
909 return 5 + jsondatalen;