Added CCM activation support.
Ylian Saint-Hilaire committed
Oct 20, 2020 at 15:15 UTC
3b355e197f8ee0c756efcb024324b0de32916ec6
4 files changed
+105
-9
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
amtmanager.js
+104
-4
@@ -71,6 +71,9 @@ module.exports.CreateAmtManager = function(parent) {
71
var i = devices.indexOf(dev);
72
if (i == -1) return false;
73
74
+ // Remove from task limiter if needed
75
+ if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; }
76
+
77
// Clean up this device
78
if (dev.amtstack != null) { dev.amtstack.wsman.comm.FailAllError = 999; delete dev.amtstack; } // Disconnect any active connections.
79
if (dev.polltimer != null) { clearInterval(dev.polltimer); delete dev.polltimer; }
@@ -86,16 +89,17 @@ module.exports.CreateAmtManager = function(parent) {
89
90
// Remove all Intel AMT devices for a given nodeid
91
function removeDevice(nodeid) {
89
- // Remove from task limiter if needed
90
- if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; }
91
-
92
// Find the devices in the list
93
var devices = obj.amtDevices[nodeid];
94
if (devices == null) return false;
95
96
for (var i in devices) {
97
- // Clean up this device
97
var dev = devices[i];
98
+
99
+ // Remove from task limiter if needed
100
+ if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; }
101
+
102
+ // Clean up this device
103
if (dev.amtstack != null) { dev.amtstack.wsman.comm.FailAllError = 999; delete dev.amtstack; } // Disconnect any active connections.
104
if (dev.polltimer != null) { clearInterval(dev.polltimer); delete dev.polltimer; }
105
}
@@ -230,6 +234,12 @@ module.exports.CreateAmtManager = function(parent) {
234
function attemptInitialContact(dev) {
235
parent.debug('amt', "Attempt Initial Contact", dev.name, dev.connType);
236
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;
241
+ }
242
+
243
if ((dev.acctry == null) && ((typeof dev.intelamt.user != 'string') || (typeof dev.intelamt.pass != 'string'))) {
244
if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { removeAmtDevice(dev); return; }
245
}
@@ -435,6 +445,7 @@ module.exports.CreateAmtManager = function(parent) {
445
if (dev.aquired.pass && (typeof dev.aquired.pass == 'string') && (dev.aquired.pass != device.intelamt.pass)) { change = 1; log = 1; device.intelamt.pass = dev.aquired.pass; changes.push('AMT pass'); }
446
if (dev.aquired.realm && (typeof dev.aquired.realm == 'string') && (dev.aquired.realm != device.intelamt.realm)) { change = 1; log = 1; device.intelamt.realm = dev.aquired.realm; changes.push('AMT realm'); }
447
if (dev.aquired.hash && (typeof dev.aquired.hash == 'string') && (dev.aquired.hash != device.intelamt.hash)) { change = 1; log = 1; device.intelamt.hash = dev.aquired.hash; changes.push('AMT hash'); }
448
+ if (dev.aquired.tls && (typeof dev.aquired.tls == 'number') && (dev.aquired.tls != device.intelamt.tls)) { change = 1; log = 1; device.intelamt.tls = dev.aquired.tls; changes.push('AMT TLS'); }
449
if (device.intelamt.state != 2) { change = 1; log = 1; device.intelamt.state = 2; changes.push('AMT state'); }
450
451
// Update Intel AMT flags if needed
@@ -672,6 +683,11 @@ module.exports.CreateAmtManager = function(parent) {
683
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
684
if (status != 200) { dev.consoleMsg("Failed to generate a key pair (" + status + ")."); removeAmtDevice(dev); return; }
685
686
+ // Check that we get a key pair reference
687
+ var x = null;
688
+ try { x = responses.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']; } catch (ex) { }
689
+ if (x == null) { dev.consoleMsg("Unable to get key pair reference."); removeAmtDevice(dev); return; }
690
+
691
// Get the new key pair
692
dev.amtstack.Enum('AMT_PublicPrivateKeyPair', function (stack, name, responses, status, tag) {
693
const dev = stack.dev;
@@ -700,6 +716,12 @@ module.exports.CreateAmtManager = function(parent) {
716
717
// Place the resulting signed certificate back into AMT
718
var pem = obj.parent.certificateOperations.forge.pki.certificateToPem(cert).replace(/(\r\n|\n|\r)/gm, '');
719
+
720
+ // Set the certificate finderprint (SHA1)
721
+ var md = obj.parent.certificateOperations.forge.md.sha1.create();
722
+ md.update(obj.parent.certificateOperations.forge.asn1.toDer(obj.parent.certificateOperations.forge.pki.certificateToAsn1(cert)).getBytes());
723
+ dev.aquired.xhash = md.digest().toHex();
724
+
725
dev.amtstack.AMT_PublicKeyManagementService_AddCertificate(pem.substring(27, pem.length - 25), function (stack, name, responses, status) {
726
const dev = stack.dev;
727
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
@@ -760,6 +782,13 @@ module.exports.CreateAmtManager = function(parent) {
782
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
783
if (status != 200) { dev.consoleMsg("Failed perform commit (" + status + ")."); removeAmtDevice(dev); return; }
784
dev.consoleMsg("Enabled TLS");
785
+
786
+ // Update device in the database
787
+ dev.aquired.tls = 1;
788
+ dev.aquired.hash = dev.aquired.xhash;
789
+ delete dev.aquired.xhash;
790
+ UpdateDevice(dev);
791
+
792
// TODO: Switch our communications to TLS (Restart our management of this node)
793
devTaskCompleted(dev);
794
});
@@ -1159,6 +1188,70 @@ module.exports.CreateAmtManager = function(parent) {
1188
devTaskCompleted(dev);
1189
}
1190
1191
+
1192
+ //
1193
+ // Intel AMT Activation
1194
+ //
1195
+
1196
+ function activateIntelAmt(dev) {
1197
+ // Find the Intel AMT policy
1198
+ const mesh = parent.webserver.meshes[dev.meshid];
1199
+ if (mesh == null) { dev.consoleMsg("Unable to find device group."); removeAmtDevice(dev); return; }
1200
+ var amtPolicy = 0; // 0 = Do nothing, 1 = Deactivate CCM, 2 = CCM, 3 = ACM
1201
+ if (mesh.amt != null) { if (mesh.amt.type) { amtPolicy = mesh.amt.type; } }
1202
+ if ((typeof dev.mpsConnection.tag.meiState.OsAdmin != 'object') || (typeof dev.mpsConnection.tag.meiState.OsAdmin.user != 'string') || (typeof dev.mpsConnection.tag.meiState.OsAdmin.pass != 'string')) { amtPolicy = 0; }
1203
+ if (amtPolicy == 0) { removeAmtDevice(dev); return; } // Do nothing, we should not have gotten this CIRA-LMS connection.
1204
+ if (amtPolicy == 2) { activateIntelAmtCcm(dev, mesh.amt.password); }
1205
+ }
1206
+
1207
+ function activateIntelAmtCcm(dev, password) {
1208
+ console.log('Intel AMT CCM Activation Required: ' + dev.name, dev.nodeid);
1209
+ if ((password == null) || (password == '')) { password = getRandomAmtPassword(); }
1210
+ dev.temp = { pass: password };
1211
+
1212
+ // Setup the WSMAN stack, no TLS
1213
+ var comm = CreateWsmanComm(dev.nodeid, 16992, dev.mpsConnection.tag.meiState.OsAdmin.user, dev.mpsConnection.tag.meiState.OsAdmin.pass, 0, null, dev.mpsConnection); // No TLS
1214
+ var wsstack = WsmanStackCreateService(comm);
1215
+ dev.amtstack = AmtStackCreateService(wsstack);
1216
+ dev.amtstack.dev = dev;
1217
+ dev.amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activateIntelAmtCcmEx1);
1218
+ }
1219
+
1220
+ function activateIntelAmtCcmEx1(stack, name, responses, status) {
1221
+ const dev = stack.dev;
1222
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1223
+ if (status != 200) { dev.consoleMsg("Failed to get Intel AMT state."); removeAmtDevice(dev); return; }
1224
+ if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { dev.consoleMsg("Client control mode activation not allowed."); removeAmtDevice(dev); return; }
1225
+ dev.amtstack.IPS_HostBasedSetupService_Setup(2, hex_md5('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + dev.temp.pass).substring(0, 32), null, null, null, null, activateIntelAmtCcmEx2);
1226
+ }
1227
+
1228
+ function activateIntelAmtCcmEx2(stack, name, responses, status) {
1229
+ const dev = stack.dev;
1230
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1231
+ if (status != 200) { dev.consoleMsg("Failed to activate Intel AMT to CCM."); removeAmtDevice(dev); return; }
1232
+ obj.parent.mpsserver.SendJsonControl(dev.mpsConnection, { action: 'mestate' }); // Request an MEI state refresh
1233
+
1234
+ // Update the device
1235
+ dev.aquired = {};
1236
+ dev.aquired.controlMode = 1; // 1 = CCM, 2 = ACM
1237
+ var verSplit = dev.amtstack.wsman.comm.amtVersion.split('.');
1238
+ if (verSplit.length >= 3) { dev.aquired.version = verSplit[0] + '.' + verSplit[1] + '.' + verSplit[2]; dev.aquired.majorver = parseInt(verSplit[0]); dev.aquired.minorver = parseInt(verSplit[1]); }
1239
+ dev.aquired.realm = dev.amtstack.wsman.comm.digestRealm;
1240
+ dev.aquired.user = 'admin';
1241
+ dev.aquired.pass = dev.temp.pass;
1242
+ dev.aquired.lastContact = Date.now();
1243
+ dev.aquired.tls = 0;
1244
+ UpdateDevice(dev);
1245
+
1246
+ // Success, switch to managing this device
1247
+ dev.consoleMsg("Succesfully activated Intel AMT in CCM mode.");
1248
+
1249
+ // Wait 8 seconds before attempting to manage this device in CCM
1250
+ var f = function doManage() { if (isAmtDeviceValid(dev)) { attemptInitialContact(doManage.dev); } }
1251
+ f.dev = dev;
1252
+ setTimeout(f, 8000);
1253
+ }
1254
+
1255
//
1256
// General Methods
1257
//
@@ -1190,6 +1283,13 @@ module.exports.CreateAmtManager = function(parent) {
1283
}
1284
}
1285
1286
+ // Generate a random Intel AMT password
1287
+ function checkAmtPassword(p) { return (p.length > 7) && (/\d/.test(p)) && (/[a-z]/.test(p)) && (/[A-Z]/.test(p)) && (/\W/.test(p)); }
1288
+ function getRandomAmtPassword() { var p; do { p = Buffer.from(obj.crypto.randomBytes(9), 'binary').toString('base64').split('/').join('@'); } while (checkAmtPassword(p) == false); return p; }
1289
+ function getRandomPassword() { return Buffer.from(obj.crypto.randomBytes(9), 'binary').toString('base64').split('/').join('@'); }
1290
+ function getRandomLowerCase(len) { var r = '', random = obj.crypto.randomBytes(len); for (var i = 0; i < len; i++) { r += String.fromCharCode(97 + (random[i] % 26)); } return r; }
1291
+
1292
+ function hex_md5(str) { return obj.parent.crypto.createHash('md5').update(str).digest('hex'); }
1293
function Clone(v) { return JSON.parse(JSON.stringify(v)); }
1294
function MakeToArray(v) { if (!v || v == null || typeof v == 'object') return v; return [v]; }
1295
function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
views/default.handlebars
+1
-5
@@ -9571,11 +9571,7 @@
9571
if (xxdialogMode) return;
9572
var x = '', acmoption = '';
9573
if ((features & 0x100000) != 0) { acmoption = '<option value=3>' + "Simple Admin Control Mode (ACM)" + '</option>'; }
9574
- if (currentMesh.mtype == 1) {
9575
- x += addHtmlValue("Type", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "No Policy" + '</option><option value=2>' + "Simple Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
9576
- } else {
9577
- x += addHtmlValue("Type", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "No Policy" + '</option><option value=1>' + "Deactivate Client Control Mode (CCM)" + '</option><option value=2>' + "Simple Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
9578
- }
9574
+ x += addHtmlValue("Type", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "No Policy" + '</option><option value=1>' + "Deactivate Client Control Mode (CCM)" + '</option><option value=2>' + "Simple Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
9575
x += '<div id=dp20amtpolicydiv></div>';
9576
setDialogMode(2, "Intel® AMT Policy", 3, p20editMeshAmtEx, x);
9577
if (currentMesh.amt) { Q('dp20amtpolicy').value = currentMesh.amt.type; }