AMT stack and AMT password trials improvements.

Ylian Saint-Hilaire committed Apr 5, 2021 at 14:01 UTC 3f6856cedc82664e508ed94487768a7a8da43673
2 files changed +61 -34
amt/amt-wsman-comm.js
+11 -8
@@ -252,7 +252,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
252 obj.socket.setTimeout(60000); // Set socket idle timeout
253 obj.socket.on('error', function (ex) { obj.xtlsMethod = 1 - obj.xtlsMethod; });
254 obj.socket.on('close', obj.xxOnSocketClosed);
255 - obj.socket.on('timeout', obj.xxOnSocketTimeout);
255 + obj.socket.on('timeout', obj.destroy);
256
257 // Decrypted tunnel from TLS communcation to be forwarded to websocket
258 obj.socket.on('data', function (data) { try { obj.xxOnSocketData(data.toString('binary')); } catch (e) { } }); // AMT/TLS ---> WS
@@ -272,7 +272,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
272 obj.socket.setTimeout(60000); // Set socket idle timeout
273 obj.socket.on('data', obj.xxOnSocketData);
274 obj.socket.on('close', obj.xxOnSocketClosed);
275 - obj.socket.on('timeout', obj.xxOnSocketTimeout);
275 + obj.socket.on('timeout', obj.destroy);
276 obj.socket.on('error', obj.xxOnSocketClosed);
277 obj.socket.connect(obj.port, obj.host, obj.xxOnSocketConnected);
278 } else {
@@ -289,7 +289,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
289 obj.socket.setTimeout(60000); // Set socket idle timeout
290 obj.socket.on('data', obj.xxOnSocketData);
291 obj.socket.on('close', obj.xxOnSocketClosed);
292 - obj.socket.on('timeout', obj.xxOnSocketTimeout);
292 + obj.socket.on('timeout', obj.destroy);
293 obj.socket.on('error', function (ex) { if (ex.message && ex.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } });
294 }
295 obj.socket.setNoDelay(true); // Disable nagle. We will encode each WSMAN request as a single send block and want to send it at once. This may help Intel AMT handle pipelining?
@@ -452,6 +452,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
452 //obj.Debug("xxOnSocketClosed");
453 obj.socketState = 0;
454 if (obj.socket != null) {
455 + if (obj.socket.removeAllListeners) { obj.socket.removeAllListeners(); }
456 try {
457 if (obj.mpsConnection == null) {
458 obj.socket.destroy();
@@ -468,17 +469,19 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
469 }
470 }
471
471 - obj.xxOnSocketTimeout = function () {
472 + obj.destroy = function () {
473 if (obj.socket != null) {
474 + if (obj.socket.removeAllListeners) { obj.socket.removeAllListeners(); }
475 try {
476 if (obj.mpsConnection == null) {
477 obj.socket.destroy();
478 } else {
477 - if (obj.cirasocket != null) { obj.cirasocket.close(); } else { obj.socket.close(); }
479 + if (obj.cirasocket != null) { obj.cirasocket.close(); } else { obj.socket.close(); }
480 }
481 } catch (ex) { }
480 - obj.socket = null;
481 - obj.cirasocket = null;
482 + delete obj.socket;
483 + delete obj.cirasocket;
484 + obj.socketState = 0;
485 }
486 }
487
@@ -492,7 +495,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn
495 obj.CancelAllQueries = function (s) {
496 obj.FailAllError = s;
497 while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
495 - if (obj.socket != null) { obj.socket.end(); obj.socket = null; obj.socketState = 0; }
498 + obj.destroy();
499 }
500
501 // Private method
amtmanager.js
+50 -26
@@ -127,7 +127,7 @@ module.exports.CreateAmtManager = function (parent) {
127 if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; }
128
129 // Clean up this device
130 - if (dev.amtstack != null) { dev.amtstack.wsman.comm.FailAllError = 999; delete dev.amtstack; } // Disconnect any active connections.
130 + if (dev.amtstack != null) { dev.amtstack.CancelAllQueries(999); delete dev.amtstack.dev; delete dev.amtstack; }
131 if (dev.polltimer != null) { clearInterval(dev.polltimer); delete dev.polltimer; }
132
133 // Remove the device from the list
@@ -419,7 +419,14 @@ module.exports.CreateAmtManager = function (parent) {
419
420 // Attempt to perform initial contact with Intel AMT
421 function attemptInitialContact(dev) {
422 - delete dev.amtstack; // If there is a WSMAn stack setup, clean it up now.
422 + // If there is a WSMAN stack setup, clean it up now.
423 + if (dev.amtstack != null) {
424 + dev.amtstack.CancelAllQueries(999);
425 + delete dev.amtstack.dev;
426 + delete dev.amtstack;
427 + }
428 +
429 + delete dev.amtstack;
430 parent.debug('amt', dev.name, "Attempt Initial Contact", ["CIRA", "CIRA-Relay", "CIRA-LMS", "Local"][dev.connType]);
431
432 // Check Intel AMT policy when CIRA-LMS connection is in use.
@@ -445,11 +452,42 @@ module.exports.CreateAmtManager = function (parent) {
452 }
453 }
454
448 - // See if we need to try different credentials
449 - if ((dev.acctry == null) && ((typeof dev.intelamt.user != 'string') || (typeof dev.intelamt.pass != 'string'))) {
450 - if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { removeAmtDevice(dev, 8); return; }
455 + // See what username/password we need to try
456 + if (dev.acctry == null) {
457 + dev.acctry = [];
458 +
459 + // Add the know Intel AMT password for this device if available
460 + if ((typeof dev.intelamt.user == 'string') && (typeof dev.intelamt.pass == 'string')) { dev.acctry.push([dev.intelamt.user, dev.intelamt.pass]); }
461 +
462 + // Add the policy password as an alternative
463 + if ((typeof dev.policy.password == 'string') && (dev.policy.password != '')) { dev.acctry.push(['admin', dev.policy.password]); }
464 +
465 + // Add any configured admin account as alternatives
466 + if (obj.amtAdminAccounts[dev.domainid] != null) { for (var i in obj.amtAdminAccounts[dev.domainid]) { dev.acctry.push([obj.amtAdminAccounts[dev.domainid][i].user, obj.amtAdminAccounts[dev.domainid][i].pass]); } }
467 +
468 + // Add any previous passwords for the device UUID as alternative
469 + if ((parent.amtPasswords != null) && (dev.mpsConnection != null) && (dev.mpsConnection.tag != null) && (dev.mpsConnection.tag.meiState != null) && (dev.mpsConnection.tag.meiState.UUID != null) && (parent.amtPasswords[dev.mpsConnection.tag.meiState.UUID] != null)) {
470 + for (var i in parent.amtPasswords[dev.mpsConnection.tag.meiState.UUID]) {
471 + dev.acctry.push(['admin', parent.amtPasswords[dev.mpsConnection.tag.meiState.UUID][i]]);
472 + }
473 + }
474 +
475 + // Remove any duplicates user/passwords
476 + var acctry2 = [];
477 + for (var i = 0; i < dev.acctry.length; i++) {
478 + var found = false;
479 + for (var j = 0; j < acctry2.length; j++) { if ((dev.acctry[i][0] == acctry2[j][0]) && (dev.acctry[i][1] == acctry2[j][1])) { found = true; } }
480 + if (found == false) { acctry2.push(dev.acctry[i]); }
481 + }
482 + dev.acctry = acctry2;
483 +
484 + // If we have passwords to try, try the first one now.
485 + if (dev.acctry.length == 0) { removeAmtDevice(dev, 8); return; }
486 }
487
488 + if ((dev.acctry == null) || (dev.acctry.length == 0)) { removeAmtDevice(dev, 9); return; } // No Intel AMT credentials to try
489 + var user = dev.acctry[0][0], pass = dev.acctry[0][1]; // Try the first user/pass in the list
490 +
491 switch (dev.connType) {
492 case 0: // CIRA
493 // Handle the case where the Intel AMT CIRA is connected (connType 0)
@@ -459,12 +497,6 @@ module.exports.CreateAmtManager = function (parent) {
497 var ciraconn = dev.mpsConnection;
498 if ((ciraconn == null) || (ciraconn.tag == null) || (ciraconn.tag.boundPorts == null)) { removeAmtDevice(dev, 9); return; } // CIRA connection is not on this server, no need to deal with this device anymore.
499
462 - // See what user/pass to try.
463 - var user = null, pass = null;
464 - if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; }
465 - else if (dev.acctry == 'policy') { user = 'admin'; pass = dev.policy.password; }
466 - else if (typeof dev.acctry == 'number') { user = obj.amtAdminAccounts[dev.domainid][dev.acctry].user; pass = obj.amtAdminAccounts[dev.domainid][dev.acctry].pass; }
467 -
500 // See if we need to perform TLS or not. We prefer not to do TLS within CIRA.
501 var dotls = -1;
502 if (ciraconn.tag.boundPorts.indexOf('16992')) { dotls = 0; }
@@ -492,12 +524,6 @@ module.exports.CreateAmtManager = function (parent) {
524 var ciraconn = dev.mpsConnection;
525 if ((ciraconn == null) || (ciraconn.tag == null) || (ciraconn.tag.boundPorts == null)) { removeAmtDevice(dev, 11); return; } // Relay connection not valid
526
495 - // See what user/pass to try.
496 - var user = null, pass = null;
497 - if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; }
498 - else if (dev.acctry == 'policy') { user = 'admin'; pass = dev.policy.password; }
499 - else if (typeof dev.acctry == 'number') { user = obj.amtAdminAccounts[dev.domainid][dev.acctry].user; pass = obj.amtAdminAccounts[dev.domainid][dev.acctry].pass; }
500 -
527 // Connect now
528 var comm;
529 if (dev.tlsfail !== true) {
@@ -530,12 +556,6 @@ module.exports.CreateAmtManager = function (parent) {
556 } else {
557 // No active connections
558
533 - // See what user/pass to try.
534 - var user = null, pass = null;
535 - if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; }
536 - else if (dev.acctry == 'policy') { user = 'admin'; pass = dev.policy.password; }
537 - else if (typeof dev.acctry == 'number') { user = obj.amtAdminAccounts[dev.domainid][dev.acctry].user; pass = obj.amtAdminAccounts[dev.domainid][dev.acctry].pass; }
538 -
559 // Connect now
560 var comm;
561 if (dev.tlsfail !== true) {
@@ -631,9 +651,13 @@ module.exports.CreateAmtManager = function (parent) {
651 dev.tlsfail = true; attemptInitialContact(dev); return;
652 } else if (status == 401) {
653 // Authentication error, see if we can use alternative credentials
634 - if ((dev.acctry == null) && (typeof dev.policy.password == 'string') && (dev.policy.password != '')) { dev.acctry = 'policy'; attemptInitialContact(dev); return; }
635 - if (((dev.acctry == null) || (dev.acctry == 'policy')) && (obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; attemptInitialContact(dev); return; }
636 - if ((dev.acctry != null) && (obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > (dev.acctry + 1))) { dev.acctry++; attemptInitialContact(dev); return; }
654 + if (dev.acctry != null) {
655 + // Remove the first password from the trial list since it did not work.
656 + if (dev.acctry.length > 0) { dev.acctry.shift(); }
657 +
658 + // We have another password to try, hold 20 second and try the next user/password.
659 + if (dev.acctry.length > 0) { setTimeout(function () { if (isAmtDeviceValid(dev)) { attemptInitialContact(dev); } }, 20000); return; }
660 + }
661
662 // If this devics is in CCM mode and we have a bad password reset policy, do it now.
663 if ((dev.connType == 2) && (dev.policy.badPass == 1) && (dev.mpsConnection != null) && (dev.mpsConnection.tag != null) && (dev.mpsConnection.tag.meiState != null) && (dev.mpsConnection.tag.meiState.Flags != null) && ((dev.mpsConnection.tag.meiState.Flags & 2) != 0)) {