From 3f6856cedc82664e508ed94487768a7a8da43673 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Mon, 5 Apr 2021 14:01:21 -0700 Subject: [PATCH] AMT stack and AMT password trials improvements. --- amt/amt-wsman-comm.js | 19 ++++++----- amtmanager.js | 76 ++++++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/amt/amt-wsman-comm.js b/amt/amt-wsman-comm.js index 82160349..608f171d 100644 --- a/amt/amt-wsman-comm.js +++ b/amt/amt-wsman-comm.js @@ -252,7 +252,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn obj.socket.setTimeout(60000); // Set socket idle timeout obj.socket.on('error', function (ex) { obj.xtlsMethod = 1 - obj.xtlsMethod; }); obj.socket.on('close', obj.xxOnSocketClosed); - obj.socket.on('timeout', obj.xxOnSocketTimeout); + obj.socket.on('timeout', obj.destroy); // Decrypted tunnel from TLS communcation to be forwarded to websocket 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 obj.socket.setTimeout(60000); // Set socket idle timeout obj.socket.on('data', obj.xxOnSocketData); obj.socket.on('close', obj.xxOnSocketClosed); - obj.socket.on('timeout', obj.xxOnSocketTimeout); + obj.socket.on('timeout', obj.destroy); obj.socket.on('error', obj.xxOnSocketClosed); obj.socket.connect(obj.port, obj.host, obj.xxOnSocketConnected); } else { @@ -289,7 +289,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn obj.socket.setTimeout(60000); // Set socket idle timeout obj.socket.on('data', obj.xxOnSocketData); obj.socket.on('close', obj.xxOnSocketClosed); - obj.socket.on('timeout', obj.xxOnSocketTimeout); + obj.socket.on('timeout', obj.destroy); obj.socket.on('error', function (ex) { if (ex.message && ex.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } }); } 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 //obj.Debug("xxOnSocketClosed"); obj.socketState = 0; if (obj.socket != null) { + if (obj.socket.removeAllListeners) { obj.socket.removeAllListeners(); } try { if (obj.mpsConnection == null) { obj.socket.destroy(); @@ -468,17 +469,19 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn } } - obj.xxOnSocketTimeout = function () { + obj.destroy = function () { if (obj.socket != null) { + if (obj.socket.removeAllListeners) { obj.socket.removeAllListeners(); } try { if (obj.mpsConnection == null) { obj.socket.destroy(); } else { - if (obj.cirasocket != null) { obj.cirasocket.close(); } else { obj.socket.close(); } + if (obj.cirasocket != null) { obj.cirasocket.close(); } else { obj.socket.close(); } } } catch (ex) { } - obj.socket = null; - obj.cirasocket = null; + delete obj.socket; + delete obj.cirasocket; + obj.socketState = 0; } } @@ -492,7 +495,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, mpsConn obj.CancelAllQueries = function (s) { obj.FailAllError = s; while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); } - if (obj.socket != null) { obj.socket.end(); obj.socket = null; obj.socketState = 0; } + obj.destroy(); } // Private method diff --git a/amtmanager.js b/amtmanager.js index 3cd388a1..584fa37b 100644 --- a/amtmanager.js +++ b/amtmanager.js @@ -127,7 +127,7 @@ module.exports.CreateAmtManager = function (parent) { if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; } // Clean up this device - if (dev.amtstack != null) { dev.amtstack.wsman.comm.FailAllError = 999; delete dev.amtstack; } // Disconnect any active connections. + if (dev.amtstack != null) { dev.amtstack.CancelAllQueries(999); delete dev.amtstack.dev; delete dev.amtstack; } if (dev.polltimer != null) { clearInterval(dev.polltimer); delete dev.polltimer; } // Remove the device from the list @@ -419,7 +419,14 @@ module.exports.CreateAmtManager = function (parent) { // Attempt to perform initial contact with Intel AMT function attemptInitialContact(dev) { - delete dev.amtstack; // If there is a WSMAn stack setup, clean it up now. + // If there is a WSMAN stack setup, clean it up now. + if (dev.amtstack != null) { + dev.amtstack.CancelAllQueries(999); + delete dev.amtstack.dev; + delete dev.amtstack; + } + + delete dev.amtstack; parent.debug('amt', dev.name, "Attempt Initial Contact", ["CIRA", "CIRA-Relay", "CIRA-LMS", "Local"][dev.connType]); // Check Intel AMT policy when CIRA-LMS connection is in use. @@ -445,11 +452,42 @@ module.exports.CreateAmtManager = function (parent) { } } - // See if we need to try different credentials - if ((dev.acctry == null) && ((typeof dev.intelamt.user != 'string') || (typeof dev.intelamt.pass != 'string'))) { - if ((obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; } else { removeAmtDevice(dev, 8); return; } + // See what username/password we need to try + if (dev.acctry == null) { + dev.acctry = []; + + // Add the know Intel AMT password for this device if available + if ((typeof dev.intelamt.user == 'string') && (typeof dev.intelamt.pass == 'string')) { dev.acctry.push([dev.intelamt.user, dev.intelamt.pass]); } + + // Add the policy password as an alternative + if ((typeof dev.policy.password == 'string') && (dev.policy.password != '')) { dev.acctry.push(['admin', dev.policy.password]); } + + // Add any configured admin account as alternatives + 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]); } } + + // Add any previous passwords for the device UUID as alternative + 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)) { + for (var i in parent.amtPasswords[dev.mpsConnection.tag.meiState.UUID]) { + dev.acctry.push(['admin', parent.amtPasswords[dev.mpsConnection.tag.meiState.UUID][i]]); + } + } + + // Remove any duplicates user/passwords + var acctry2 = []; + for (var i = 0; i < dev.acctry.length; i++) { + var found = false; + 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; } } + if (found == false) { acctry2.push(dev.acctry[i]); } + } + dev.acctry = acctry2; + + // If we have passwords to try, try the first one now. + if (dev.acctry.length == 0) { removeAmtDevice(dev, 8); return; } } + if ((dev.acctry == null) || (dev.acctry.length == 0)) { removeAmtDevice(dev, 9); return; } // No Intel AMT credentials to try + var user = dev.acctry[0][0], pass = dev.acctry[0][1]; // Try the first user/pass in the list + switch (dev.connType) { case 0: // CIRA // Handle the case where the Intel AMT CIRA is connected (connType 0) @@ -459,12 +497,6 @@ module.exports.CreateAmtManager = function (parent) { var ciraconn = dev.mpsConnection; 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. - // See what user/pass to try. - var user = null, pass = null; - if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; } - else if (dev.acctry == 'policy') { user = 'admin'; pass = dev.policy.password; } - else if (typeof dev.acctry == 'number') { user = obj.amtAdminAccounts[dev.domainid][dev.acctry].user; pass = obj.amtAdminAccounts[dev.domainid][dev.acctry].pass; } - // See if we need to perform TLS or not. We prefer not to do TLS within CIRA. var dotls = -1; if (ciraconn.tag.boundPorts.indexOf('16992')) { dotls = 0; } @@ -492,12 +524,6 @@ module.exports.CreateAmtManager = function (parent) { var ciraconn = dev.mpsConnection; if ((ciraconn == null) || (ciraconn.tag == null) || (ciraconn.tag.boundPorts == null)) { removeAmtDevice(dev, 11); return; } // Relay connection not valid - // See what user/pass to try. - var user = null, pass = null; - if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; } - else if (dev.acctry == 'policy') { user = 'admin'; pass = dev.policy.password; } - else if (typeof dev.acctry == 'number') { user = obj.amtAdminAccounts[dev.domainid][dev.acctry].user; pass = obj.amtAdminAccounts[dev.domainid][dev.acctry].pass; } - // Connect now var comm; if (dev.tlsfail !== true) { @@ -530,12 +556,6 @@ module.exports.CreateAmtManager = function (parent) { } else { // No active connections - // See what user/pass to try. - var user = null, pass = null; - if (dev.acctry == null) { user = dev.intelamt.user; pass = dev.intelamt.pass; } - else if (dev.acctry == 'policy') { user = 'admin'; pass = dev.policy.password; } - else if (typeof dev.acctry == 'number') { user = obj.amtAdminAccounts[dev.domainid][dev.acctry].user; pass = obj.amtAdminAccounts[dev.domainid][dev.acctry].pass; } - // Connect now var comm; if (dev.tlsfail !== true) { @@ -631,9 +651,13 @@ module.exports.CreateAmtManager = function (parent) { dev.tlsfail = true; attemptInitialContact(dev); return; } else if (status == 401) { // Authentication error, see if we can use alternative credentials - if ((dev.acctry == null) && (typeof dev.policy.password == 'string') && (dev.policy.password != '')) { dev.acctry = 'policy'; attemptInitialContact(dev); return; } - if (((dev.acctry == null) || (dev.acctry == 'policy')) && (obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > 0)) { dev.acctry = 0; attemptInitialContact(dev); return; } - if ((dev.acctry != null) && (obj.amtAdminAccounts[dev.domainid] != null) && (obj.amtAdminAccounts[dev.domainid].length > (dev.acctry + 1))) { dev.acctry++; attemptInitialContact(dev); return; } + if (dev.acctry != null) { + // Remove the first password from the trial list since it did not work. + if (dev.acctry.length > 0) { dev.acctry.shift(); } + + // We have another password to try, hold 20 second and try the next user/password. + if (dev.acctry.length > 0) { setTimeout(function () { if (isAmtDeviceValid(dev)) { attemptInitialContact(dev); } }, 20000); return; } + } // If this devics is in CCM mode and we have a bad password reset policy, do it now. 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)) {