From 90d2d7b21b9b93668311c41988563e5346873de7 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 6 Apr 2022 19:55:32 -0700 Subject: [PATCH] More work on AMT 802.1x support. --- amt/amt.js | 5 +- amtmanager.js | 199 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 156 insertions(+), 48 deletions(-) diff --git a/amt/amt.js b/amt/amt.js index 0ec62801..4699e9ea 100644 --- a/amt/amt.js +++ b/amt/amt.js @@ -304,7 +304,10 @@ function AmtStackCreateService(wsmanStack) { obj.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch = function (Ta0, Tm1, Tm2, callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "SetHighAccuracyTimeSynch", { "Ta0": Ta0, "Tm1": Tm1, "Tm2": Tm2 }, callback_func, tag); } obj.AMT_UserInitiatedConnectionService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_UserInitiatedConnectionService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); } obj.AMT_WebUIService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func, tag) { obj.Exec("AMT_WebUIService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func, tag); } - obj.AMT_WiFiPortConfigurationService_AddWiFiSettings = function (WiFiEndpoint, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { obj.ExecWithXml("AMT_WiFiPortConfigurationService", "AddWiFiSettings", { "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); } + obj.AMT_WiFiPortConfigurationService_AddWiFiSettings = function (WiFiEndpoint, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { + console.log(JSON.stringify({ "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, null, 2)); + obj.ExecWithXml("AMT_WiFiPortConfigurationService", "AddWiFiSettings", { "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); + } obj.AMT_WiFiPortConfigurationService_UpdateWiFiSettings = function (WiFiEndpointSettings, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { obj.ExecWithXml("AMT_WiFiPortConfigurationService", "UpdateWiFiSettings", { "WiFiEndpointSettings": WiFiEndpointSettings, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); } obj.AMT_WiFiPortConfigurationService_DeleteAllITProfiles = function (_method_dummy, callback_func) { obj.Exec("AMT_WiFiPortConfigurationService", "DeleteAllITProfiles", { "_method_dummy": _method_dummy }, callback_func); } obj.AMT_WiFiPortConfigurationService_DeleteAllUserProfiles = function (_method_dummy, callback_func) { obj.Exec("AMT_WiFiPortConfigurationService", "DeleteAllUserProfiles", { "_method_dummy": _method_dummy }, callback_func); } diff --git a/amtmanager.js b/amtmanager.js index 181303d3..738fe125 100644 --- a/amtmanager.js +++ b/amtmanager.js @@ -737,23 +737,26 @@ module.exports.CreateAmtManager = function (parent) { attemptCiraSync(dev, function (dev) { // Check Intel AMT settings attemptSettingsSync(dev, function (dev) { - // See if we need to get hardware inventory - attemptFetchHardwareInventory(dev, function (dev) { - dev.consoleMsg('Done.'); + // Clean unused certificates + attemptCleanCertsSync(dev, function (dev) { + // See if we need to get hardware inventory + attemptFetchHardwareInventory(dev, function (dev) { + dev.consoleMsg('Done.'); - // Remove from task limiter if needed - if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; } + // Remove from task limiter if needed + if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; } - if (dev.connType != 2) { - // Start power polling if not connected to LMS - var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); } - ppfunc.dev = dev; - dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds. - fetchPowerState(dev); - } else { - // For LMS connections, close now. - dev.controlMsg({ action: 'close' }); - } + if (dev.connType != 2) { + // Start power polling if not connected to LMS + var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); } + ppfunc.dev = dev; + dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds. + fetchPowerState(dev); + } else { + // For LMS connections, close now. + dev.controlMsg({ action: 'close' }); + } + }); }); }); }); @@ -1394,9 +1397,7 @@ module.exports.CreateAmtManager = function (parent) { // Remove any unlinked private keys for (var i in xxCertPrivateKeys) { if (!xxCertPrivateKeys[i].XCert) { - console.log('PrivateKey-Removing'); dev.amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertPrivateKeys[i]['InstanceID'] }, function (stack, name, response, status) { - console.log('PrivateKey-Removed'); //if (status == 200) { dev.consoleMsg("Removed unassigned private key pair."); } }); } @@ -1550,6 +1551,8 @@ module.exports.CreateAmtManager = function (parent) { // Check 802.1x root certificate function perform8021xRootCertCheck(dev) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + // Check if there is a root certificate to add, if we already have it, get the instance id. if (dev.netAuthCredentials.rootcert) { var matchingRootCertId = null; @@ -1586,6 +1589,8 @@ module.exports.CreateAmtManager = function (parent) { // Check 802.1x client certificate function perform8021xClientCertCheck(dev) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + if (dev.netAuthCredentials.certificate) { // The new 802.1x profile includes a new certificate, add it now before adding the 802.1x profiles // dev.netAuthCredentials.certificate must be in DER encoded format @@ -1618,6 +1623,8 @@ module.exports.CreateAmtManager = function (parent) { // Set the 802.1x wired profile function attempt8021xSyncEx(dev, devNetAuthData) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + // Unpack const domain = devNetAuthData.domain; const devNetAuthProfile = devNetAuthData.devNetAuthProfile; @@ -1677,12 +1684,9 @@ module.exports.CreateAmtManager = function (parent) { } } - console.log('netAuthProfile', netAuthProfile); - dev.amtstack.Put('AMT_8021XProfile', netAuthProfile, function (stack, name, responses, status) { const dev = stack.dev; if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. - console.log('AMT_8021XProfile-PUT', responses); if (status == 200) { dev.consoleMsg("802.1x wired profile set."); } else { dev.consoleMsg("Unable to set 802.1x wired profile."); } attemptWifiSyncEx(dev, devNetAuthData); }); @@ -1693,6 +1697,8 @@ module.exports.CreateAmtManager = function (parent) { } function attemptWifiSyncEx(dev, devNetAuthData) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + // Unpack const domain = devNetAuthData.domain; const devNetAuthProfile = devNetAuthData.devNetAuthProfile; @@ -1705,7 +1711,7 @@ module.exports.CreateAmtManager = function (parent) { if (wirelessConfig) { // Add missing WIFI profiles - var nextPriority = 0; + var nextPriority = 1; for (var i in profilesToAdd) { while (prioritiesInUse.indexOf(nextPriority) >= 0) { nextPriority++; } // Figure out the next available priority slot. var profileToAdd = profilesToAdd[i]; @@ -1741,8 +1747,26 @@ module.exports.CreateAmtManager = function (parent) { if (domain.amtmanager['802.1x'].password) { netAuthProfile['Password'] = domain.amtmanager['802.1x'].password; } if (domain.amtmanager['802.1x'].domain) { netAuthProfile['Domain'] = domain.amtmanager['802.1x'].domain; } if (domain.amtmanager['802.1x'].authenticationprotocol > 3) { domain.amtmanager['ProtectedAccessCredential'] = profileToAdd['802.1x'].protectedaccesscredentialhex; netAuthProfile['PACPassword'] = profileToAdd['802.1x'].pacpassword; } - //if (parseInt(Q('idx_d12clientcert').value) >= 0) { netAuthSettingsClientCert = '
http://schemas.xmlsoap.org/ws/2004/08/addressing
http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate' + xxCertificates[parseInt(Q('idx_d12clientcert').value)]['InstanceID'] + ''; } - //if (parseInt(Q('idx_d12servercert').value) >= 0) { netAuthSettingsServerCaCert = '
http://schemas.xmlsoap.org/ws/2004/08/addressing
http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate' + xxCertificates[parseInt(Q('idx_d12servercert').value)]['InstanceID'] + ''; } + + /* + // Setup Client Certificate + if (devNetAuthData.certInstanceId) { + netAuthSettingsClientCert = '/wsman' + dev.amtstack.CompleteName('AMT_PublicKeyCertificate') + '' + devNetAuthData.certInstanceId + ''; + } + // Setup Server Certificate + if (devNetAuthData.rootCertInstanceId) { + netAuthSettingsServerCaCert = '/wsman' + dev.amtstack.CompleteName('AMT_PublicKeyCertificate') + '' + devNetAuthData.rootCertInstanceId + ''; + } + */ + + // Setup Client Certificate + if (devNetAuthData.certInstanceId) { + netAuthSettingsClientCert = '
http://schemas.xmlsoap.org/ws/2004/08/addressing
http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate' + devNetAuthData.certInstanceId + ''; + } + // Setup Server Certificate + if (devNetAuthData.rootCertInstanceId) { + netAuthSettingsServerCaCert = '
http://schemas.xmlsoap.org/ws/2004/08/addressing
http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate' + devNetAuthData.rootCertInstanceId + ''; + } // If we have credentials from MeshCentral Satelite, use that if (dev.netAuthCredentials != null) { @@ -1753,43 +1777,64 @@ module.exports.CreateAmtManager = function (parent) { } } prioritiesInUse.push(nextPriority); // Occupy the priority slot and add the WIFI profile. - dev.amtstack.AMT_WiFiPortConfigurationService_AddWiFiSettings(wifiep, wifiepsettinginput, netAuthProfile, netAuthSettingsClientCert, netAuthSettingsServerCaCert, function (stack, name, responses, status) { }); - } + console.log('AddWiFiSettings1'); - // Check if local WIFI profile sync is enabled, if not, enabled it. - if ((responses['AMT_WiFiPortConfigurationService'] != null) && (responses['AMT_WiFiPortConfigurationService'].response != null) && (responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 0)) { - responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] = 1; - dev.amtstack.Put('AMT_WiFiPortConfigurationService', responses['AMT_WiFiPortConfigurationService'].response, function (stack, name, response, status) { - if (status != 200) { dev.consoleMsg("Unable to enable local WIFI profile sync."); } else { dev.consoleMsg("Enabled local WIFI profile sync."); } + dev.amtstack.AMT_WiFiPortConfigurationService_AddWiFiSettings(wifiep, wifiepsettinginput, netAuthProfile, netAuthSettingsClientCert, netAuthSettingsServerCaCert, function (stack, name, response, status) { + if (status != 200) { dev.consoleMsg("Unable to set WIFI profile."); } + console.log('AddWiFiSettings2', status, response); }); } - // Change the WIFI state if needed. Right now, we always enable it. - // WifiState = { 3: "Disabled", 32768: "Enabled in S0", 32769: "Enabled in S0, Sx/AC" }; - var wifiState = 32769; // For now, always enable WIFI - if (responses['CIM_WiFiPort'].responses.Body.EnabledState != 32769) { - if (wifiState == 3) { - dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) { - const dev = stack.dev; - if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. - if (status == 200) { dev.consoleMsg("Disabled WIFI."); } - }); - } else { - dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) { - const dev = stack.dev; - if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. - if (status == 200) { dev.consoleMsg("Enabled WIFI."); } - }); - } + // Complete WIFI configuration + attemptWifiSyncEx2(dev, devNetAuthData); + } else { + // Done + devTaskCompleted(dev); + } + } + + function attemptWifiSyncEx2(dev, devNetAuthData) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + + const responses = devNetAuthData.responses; + + // Check if local WIFI profile sync is enabled, if not, enabled it. + if ((responses['AMT_WiFiPortConfigurationService'] != null) && (responses['AMT_WiFiPortConfigurationService'].response != null) && (responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 0)) { + responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] = 1; + dev.amtstack.Put('AMT_WiFiPortConfigurationService', responses['AMT_WiFiPortConfigurationService'].response, function (stack, name, response, status) { + if (status != 200) { dev.consoleMsg("Unable to enable local WIFI profile sync."); } else { dev.consoleMsg("Enabled local WIFI profile sync."); } + }); + } + + // Change the WIFI state if needed. Right now, we always enable it. + // WifiState = { 3: "Disabled", 32768: "Enabled in S0", 32769: "Enabled in S0, Sx/AC" }; + var wifiState = 32769; // For now, always enable WIFI + if (responses['CIM_WiFiPort'].responses.Body.EnabledState != 32769) { + if (wifiState == 3) { + dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) { + const dev = stack.dev; + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + if (status == 200) { dev.consoleMsg("Disabled WIFI."); } + }); + } else { + dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) { + const dev = stack.dev; + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + if (status == 200) { dev.consoleMsg("Enabled WIFI."); } + }); } } + console.log('ALL GOOD'); + // Done devTaskCompleted(dev); } // Request for a RSA key pair generation. This will be used to generate the 802.1x certificate function attempt8021xKeyGeneration(dev) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + dev.amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, function (stack, name, response, status) { if ((status != 200) || (response.Body['ReturnValue'] != 0)) { // Failed to generate a key pair @@ -1820,6 +1865,8 @@ module.exports.CreateAmtManager = function (parent) { // 802.1x request to process a Certificate Signing Request, we ask Intel AMT to sign the request function attempt8021xCRSRequest(dev, event) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + if ((event.response == null) || (event.response.keyInstanceId == null)) return; var keyPair = 'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymoushttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPair' + event.response.keyInstanceId + ''; // keyPair EPR Reference var signingAlgorithm = 1; // 0 = SHA1-RSA, 1 = SHA256-RSA @@ -2214,6 +2261,64 @@ module.exports.CreateAmtManager = function (parent) { } + // + // Intel AMT Certificate cleanup + // + + // Remove any unused, non-trusted certificates + function attemptCleanCertsSync(dev, func) { + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + dev.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', 'AMT_PublicPrivateKeyPair'], function (stack, name, responses, status) { + const dev = stack.dev; + if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request. + const domain = parent.config.domains[dev.domainid]; + if ((responses['AMT_PublicKeyCertificate'].status != 200) || (responses['AMT_PublicKeyCertificate'].status != 200)) { func(dev); return; } // We can't get the certificate list, fail and carry on. + + // Sort out the certificates + var xxCertificates = responses['AMT_PublicKeyCertificate'].responses; + var xxCertPrivateKeys = responses['AMT_PublicPrivateKeyPair'].responses; + for (var i in xxCertificates) { + xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true); + xxCertificates[i].X509CertificateBin = Buffer.from(xxCertificates[i]['X509Certificate'], 'base64').toString('binary'); + xxCertificates[i].XIssuer = parseCertName(xxCertificates[i]['Issuer']); + xxCertificates[i].XSubject = parseCertName(xxCertificates[i]['Subject']); + } + amtcert_linkCertPrivateKey(xxCertificates, xxCertPrivateKeys); // This links all certificates and private keys + dev.certDeleteTasks = 0; + + // Remove any unlinked private keys + for (var i in xxCertPrivateKeys) { + if (!xxCertPrivateKeys[i].XCert) { + dev.certDeleteTasks++; + dev.amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertPrivateKeys[i]['InstanceID'] }, function (stack, name, response, status) { + //if (status == 200) { dev.consoleMsg("Removed unassigned private key pair."); } + if (--dev.certDeleteTasks == 0) { delete dev.certDeleteTasks; func(dev); } + }); + } + } + + // Try to remove all untrusted certificates + for (var i in xxCertificates) { + if (xxCertificates[i].TrustedRootCertficate == false) { + var privateKeyInstanceId = null; + if (xxCertificates[i].XPrivateKey) { privateKeyInstanceId = { 'InstanceID': xxCertificates[i].XPrivateKey['InstanceID'] }; } + dev.certDeleteTasks++; + dev.amtstack.Delete('AMT_PublicKeyCertificate', { 'InstanceID': xxCertificates[i]['InstanceID'] }, function (stack, name, response, status, tag) { + if ((status == 200) && (tag != null)) { + // If there is a private key, delete it. + dev.amtstack.Delete('AMT_PublicPrivateKeyPair', tag, function () { + if (--dev.certDeleteTasks == 0) { delete dev.certDeleteTasks; func(dev); } + }, 0, 1); + } else { + if (--dev.certDeleteTasks == 0) { delete dev.certDeleteTasks; func(dev); } + } + }, privateKeyInstanceId); + } + } + }); + } + + // // Intel AMT Hardware Inventory and Networking //