More work on AMT 802.1x support.
Ylian Saint-Hilaire committed
Apr 6, 2022 at 19:55 UTC
90d2d7b21b9b93668311c41988563e5346873de7
2 files changed
+158
-50
amt/amt.js
+4
-1
@@ -304,7 +304,10 @@ function AmtStackCreateService(wsmanStack) {
304
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); }
305
obj.AMT_UserInitiatedConnectionService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_UserInitiatedConnectionService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
306
obj.AMT_WebUIService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func, tag) { obj.Exec("AMT_WebUIService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func, tag); }
307
- 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); }
307
+ obj.AMT_WiFiPortConfigurationService_AddWiFiSettings = function (WiFiEndpoint, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) {
308
+ console.log(JSON.stringify({ "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, null, 2));
309
+ obj.ExecWithXml("AMT_WiFiPortConfigurationService", "AddWiFiSettings", { "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func);
310
+ }
311
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); }
312
obj.AMT_WiFiPortConfigurationService_DeleteAllITProfiles = function (_method_dummy, callback_func) { obj.Exec("AMT_WiFiPortConfigurationService", "DeleteAllITProfiles", { "_method_dummy": _method_dummy }, callback_func); }
313
obj.AMT_WiFiPortConfigurationService_DeleteAllUserProfiles = function (_method_dummy, callback_func) { obj.Exec("AMT_WiFiPortConfigurationService", "DeleteAllUserProfiles", { "_method_dummy": _method_dummy }, callback_func); }
amtmanager.js
+154
-49
@@ -737,23 +737,26 @@ module.exports.CreateAmtManager = function (parent) {
737
attemptCiraSync(dev, function (dev) {
738
// Check Intel AMT settings
739
attemptSettingsSync(dev, function (dev) {
740
- // See if we need to get hardware inventory
741
- attemptFetchHardwareInventory(dev, function (dev) {
742
- dev.consoleMsg('Done.');
743
-
744
- // Remove from task limiter if needed
745
- if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; }
746
-
747
- if (dev.connType != 2) {
748
- // Start power polling if not connected to LMS
749
- var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); }
750
- ppfunc.dev = dev;
751
- dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds.
752
- fetchPowerState(dev);
753
- } else {
754
- // For LMS connections, close now.
755
- dev.controlMsg({ action: 'close' });
756
- }
740
+ // Clean unused certificates
741
+ attemptCleanCertsSync(dev, function (dev) {
742
+ // See if we need to get hardware inventory
743
+ attemptFetchHardwareInventory(dev, function (dev) {
744
+ dev.consoleMsg('Done.');
745
+
746
+ // Remove from task limiter if needed
747
+ if (dev.taskid != null) { obj.parent.taskLimiter.completed(dev.taskid); delete dev.taskLimiter; }
748
+
749
+ if (dev.connType != 2) {
750
+ // Start power polling if not connected to LMS
751
+ var ppfunc = function powerPoleFunction() { fetchPowerState(powerPoleFunction.dev); }
752
+ ppfunc.dev = dev;
753
+ dev.polltimer = new setTimeout(ppfunc, 290000); // Poll for power state every 4 minutes 50 seconds.
754
+ fetchPowerState(dev);
755
+ } else {
756
+ // For LMS connections, close now.
757
+ dev.controlMsg({ action: 'close' });
758
+ }
759
+ });
760
});
761
});
762
});
@@ -1394,9 +1397,7 @@ module.exports.CreateAmtManager = function (parent) {
1397
// Remove any unlinked private keys
1398
for (var i in xxCertPrivateKeys) {
1399
if (!xxCertPrivateKeys[i].XCert) {
1397
- console.log('PrivateKey-Removing');
1400
dev.amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertPrivateKeys[i]['InstanceID'] }, function (stack, name, response, status) {
1399
- console.log('PrivateKey-Removed');
1401
//if (status == 200) { dev.consoleMsg("Removed unassigned private key pair."); }
1402
});
1403
}
@@ -1550,6 +1551,8 @@ module.exports.CreateAmtManager = function (parent) {
1551
1552
// Check 802.1x root certificate
1553
function perform8021xRootCertCheck(dev) {
1554
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1555
+
1556
// Check if there is a root certificate to add, if we already have it, get the instance id.
1557
if (dev.netAuthCredentials.rootcert) {
1558
var matchingRootCertId = null;
@@ -1586,6 +1589,8 @@ module.exports.CreateAmtManager = function (parent) {
1589
1590
// Check 802.1x client certificate
1591
function perform8021xClientCertCheck(dev) {
1592
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1593
+
1594
if (dev.netAuthCredentials.certificate) {
1595
// The new 802.1x profile includes a new certificate, add it now before adding the 802.1x profiles
1596
// dev.netAuthCredentials.certificate must be in DER encoded format
@@ -1618,6 +1623,8 @@ module.exports.CreateAmtManager = function (parent) {
1623
1624
// Set the 802.1x wired profile
1625
function attempt8021xSyncEx(dev, devNetAuthData) {
1626
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1627
+
1628
// Unpack
1629
const domain = devNetAuthData.domain;
1630
const devNetAuthProfile = devNetAuthData.devNetAuthProfile;
@@ -1677,12 +1684,9 @@ module.exports.CreateAmtManager = function (parent) {
1684
}
1685
}
1686
1680
- console.log('netAuthProfile', netAuthProfile);
1681
-
1687
dev.amtstack.Put('AMT_8021XProfile', netAuthProfile, function (stack, name, responses, status) {
1688
const dev = stack.dev;
1689
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1685
- console.log('AMT_8021XProfile-PUT', responses);
1690
if (status == 200) { dev.consoleMsg("802.1x wired profile set."); } else { dev.consoleMsg("Unable to set 802.1x wired profile."); }
1691
attemptWifiSyncEx(dev, devNetAuthData);
1692
});
@@ -1693,6 +1697,8 @@ module.exports.CreateAmtManager = function (parent) {
1697
}
1698
1699
function attemptWifiSyncEx(dev, devNetAuthData) {
1700
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1701
+
1702
// Unpack
1703
const domain = devNetAuthData.domain;
1704
const devNetAuthProfile = devNetAuthData.devNetAuthProfile;
@@ -1705,7 +1711,7 @@ module.exports.CreateAmtManager = function (parent) {
1711
1712
if (wirelessConfig) {
1713
// Add missing WIFI profiles
1708
- var nextPriority = 0;
1714
+ var nextPriority = 1;
1715
for (var i in profilesToAdd) {
1716
while (prioritiesInUse.indexOf(nextPriority) >= 0) { nextPriority++; } // Figure out the next available priority slot.
1717
var profileToAdd = profilesToAdd[i];
@@ -1741,8 +1747,26 @@ module.exports.CreateAmtManager = function (parent) {
1747
if (domain.amtmanager['802.1x'].password) { netAuthProfile['Password'] = domain.amtmanager['802.1x'].password; }
1748
if (domain.amtmanager['802.1x'].domain) { netAuthProfile['Domain'] = domain.amtmanager['802.1x'].domain; }
1749
if (domain.amtmanager['802.1x'].authenticationprotocol > 3) { domain.amtmanager['ProtectedAccessCredential'] = profileToAdd['802.1x'].protectedaccesscredentialhex; netAuthProfile['PACPassword'] = profileToAdd['802.1x'].pacpassword; }
1744
- //if (parseInt(Q('idx_d12clientcert').value) >= 0) { netAuthSettingsClientCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d12clientcert').value)]['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>'; }
1745
- //if (parseInt(Q('idx_d12servercert').value) >= 0) { netAuthSettingsServerCaCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d12servercert').value)]['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>'; }
1750
+
1751
+ /*
1752
+ // Setup Client Certificate
1753
+ if (devNetAuthData.certInstanceId) {
1754
+ netAuthSettingsClientCert = '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + dev.amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + devNetAuthData.certInstanceId + '</w:Selector></w:SelectorSet></a:ReferenceParameters>';
1755
+ }
1756
+ // Setup Server Certificate
1757
+ if (devNetAuthData.rootCertInstanceId) {
1758
+ netAuthSettingsServerCaCert = '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + dev.amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + devNetAuthData.rootCertInstanceId + '</w:Selector></w:SelectorSet></a:ReferenceParameters>';
1759
+ }
1760
+ */
1761
+
1762
+ // Setup Client Certificate
1763
+ if (devNetAuthData.certInstanceId) {
1764
+ netAuthSettingsClientCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + devNetAuthData.certInstanceId + '</Selector></SelectorSet></ReferenceParameters>';
1765
+ }
1766
+ // Setup Server Certificate
1767
+ if (devNetAuthData.rootCertInstanceId) {
1768
+ netAuthSettingsServerCaCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + devNetAuthData.rootCertInstanceId + '</Selector></SelectorSet></ReferenceParameters>';
1769
+ }
1770
1771
// If we have credentials from MeshCentral Satelite, use that
1772
if (dev.netAuthCredentials != null) {
@@ -1753,43 +1777,64 @@ module.exports.CreateAmtManager = function (parent) {
1777
}
1778
}
1779
prioritiesInUse.push(nextPriority); // Occupy the priority slot and add the WIFI profile.
1756
- dev.amtstack.AMT_WiFiPortConfigurationService_AddWiFiSettings(wifiep, wifiepsettinginput, netAuthProfile, netAuthSettingsClientCert, netAuthSettingsServerCaCert, function (stack, name, responses, status) { });
1757
- }
1780
+ console.log('AddWiFiSettings1');
1781
1759
- // Check if local WIFI profile sync is enabled, if not, enabled it.
1760
- if ((responses['AMT_WiFiPortConfigurationService'] != null) && (responses['AMT_WiFiPortConfigurationService'].response != null) && (responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 0)) {
1761
- responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] = 1;
1762
- dev.amtstack.Put('AMT_WiFiPortConfigurationService', responses['AMT_WiFiPortConfigurationService'].response, function (stack, name, response, status) {
1763
- if (status != 200) { dev.consoleMsg("Unable to enable local WIFI profile sync."); } else { dev.consoleMsg("Enabled local WIFI profile sync."); }
1782
+ dev.amtstack.AMT_WiFiPortConfigurationService_AddWiFiSettings(wifiep, wifiepsettinginput, netAuthProfile, netAuthSettingsClientCert, netAuthSettingsServerCaCert, function (stack, name, response, status) {
1783
+ if (status != 200) { dev.consoleMsg("Unable to set WIFI profile."); }
1784
+ console.log('AddWiFiSettings2', status, response);
1785
});
1786
}
1787
1767
- // Change the WIFI state if needed. Right now, we always enable it.
1768
- // WifiState = { 3: "Disabled", 32768: "Enabled in S0", 32769: "Enabled in S0, Sx/AC" };
1769
- var wifiState = 32769; // For now, always enable WIFI
1770
- if (responses['CIM_WiFiPort'].responses.Body.EnabledState != 32769) {
1771
- if (wifiState == 3) {
1772
- dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) {
1773
- const dev = stack.dev;
1774
- if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1775
- if (status == 200) { dev.consoleMsg("Disabled WIFI."); }
1776
- });
1777
- } else {
1778
- dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) {
1779
- const dev = stack.dev;
1780
- if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1781
- if (status == 200) { dev.consoleMsg("Enabled WIFI."); }
1782
- });
1783
- }
1788
+ // Complete WIFI configuration
1789
+ attemptWifiSyncEx2(dev, devNetAuthData);
1790
+ } else {
1791
+ // Done
1792
+ devTaskCompleted(dev);
1793
+ }
1794
+ }
1795
+
1796
+ function attemptWifiSyncEx2(dev, devNetAuthData) {
1797
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1798
+
1799
+ const responses = devNetAuthData.responses;
1800
+
1801
+ // Check if local WIFI profile sync is enabled, if not, enabled it.
1802
+ if ((responses['AMT_WiFiPortConfigurationService'] != null) && (responses['AMT_WiFiPortConfigurationService'].response != null) && (responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 0)) {
1803
+ responses['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] = 1;
1804
+ dev.amtstack.Put('AMT_WiFiPortConfigurationService', responses['AMT_WiFiPortConfigurationService'].response, function (stack, name, response, status) {
1805
+ if (status != 200) { dev.consoleMsg("Unable to enable local WIFI profile sync."); } else { dev.consoleMsg("Enabled local WIFI profile sync."); }
1806
+ });
1807
+ }
1808
+
1809
+ // Change the WIFI state if needed. Right now, we always enable it.
1810
+ // WifiState = { 3: "Disabled", 32768: "Enabled in S0", 32769: "Enabled in S0, Sx/AC" };
1811
+ var wifiState = 32769; // For now, always enable WIFI
1812
+ if (responses['CIM_WiFiPort'].responses.Body.EnabledState != 32769) {
1813
+ if (wifiState == 3) {
1814
+ dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) {
1815
+ const dev = stack.dev;
1816
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1817
+ if (status == 200) { dev.consoleMsg("Disabled WIFI."); }
1818
+ });
1819
+ } else {
1820
+ dev.amtstack.CIM_WiFiPort_RequestStateChange(wifiState, null, function (stack, name, responses, status) {
1821
+ const dev = stack.dev;
1822
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1823
+ if (status == 200) { dev.consoleMsg("Enabled WIFI."); }
1824
+ });
1825
}
1826
}
1827
1828
+ console.log('ALL GOOD');
1829
+
1830
// Done
1831
devTaskCompleted(dev);
1832
}
1833
1834
// Request for a RSA key pair generation. This will be used to generate the 802.1x certificate
1835
function attempt8021xKeyGeneration(dev) {
1836
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1837
+
1838
dev.amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, function (stack, name, response, status) {
1839
if ((status != 200) || (response.Body['ReturnValue'] != 0)) {
1840
// Failed to generate a key pair
@@ -1820,6 +1865,8 @@ module.exports.CreateAmtManager = function (parent) {
1865
1866
// 802.1x request to process a Certificate Signing Request, we ask Intel AMT to sign the request
1867
function attempt8021xCRSRequest(dev, event) {
1868
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
1869
+
1870
if ((event.response == null) || (event.response.keyInstanceId == null)) return;
1871
var keyPair = '<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicPrivateKeyPair</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + event.response.keyInstanceId + '</w:Selector></w:SelectorSet></a:ReferenceParameters>'; // keyPair EPR Reference
1872
var signingAlgorithm = 1; // 0 = SHA1-RSA, 1 = SHA256-RSA
@@ -2214,6 +2261,64 @@ module.exports.CreateAmtManager = function (parent) {
2261
}
2262
2263
2264
+ //
2265
+ // Intel AMT Certificate cleanup
2266
+ //
2267
+
2268
+ // Remove any unused, non-trusted certificates
2269
+ function attemptCleanCertsSync(dev, func) {
2270
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
2271
+ dev.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', 'AMT_PublicPrivateKeyPair'], function (stack, name, responses, status) {
2272
+ const dev = stack.dev;
2273
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
2274
+ const domain = parent.config.domains[dev.domainid];
2275
+ 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.
2276
+
2277
+ // Sort out the certificates
2278
+ var xxCertificates = responses['AMT_PublicKeyCertificate'].responses;
2279
+ var xxCertPrivateKeys = responses['AMT_PublicPrivateKeyPair'].responses;
2280
+ for (var i in xxCertificates) {
2281
+ xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true);
2282
+ xxCertificates[i].X509CertificateBin = Buffer.from(xxCertificates[i]['X509Certificate'], 'base64').toString('binary');
2283
+ xxCertificates[i].XIssuer = parseCertName(xxCertificates[i]['Issuer']);
2284
+ xxCertificates[i].XSubject = parseCertName(xxCertificates[i]['Subject']);
2285
+ }
2286
+ amtcert_linkCertPrivateKey(xxCertificates, xxCertPrivateKeys); // This links all certificates and private keys
2287
+ dev.certDeleteTasks = 0;
2288
+
2289
+ // Remove any unlinked private keys
2290
+ for (var i in xxCertPrivateKeys) {
2291
+ if (!xxCertPrivateKeys[i].XCert) {
2292
+ dev.certDeleteTasks++;
2293
+ dev.amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertPrivateKeys[i]['InstanceID'] }, function (stack, name, response, status) {
2294
+ //if (status == 200) { dev.consoleMsg("Removed unassigned private key pair."); }
2295
+ if (--dev.certDeleteTasks == 0) { delete dev.certDeleteTasks; func(dev); }
2296
+ });
2297
+ }
2298
+ }
2299
+
2300
+ // Try to remove all untrusted certificates
2301
+ for (var i in xxCertificates) {
2302
+ if (xxCertificates[i].TrustedRootCertficate == false) {
2303
+ var privateKeyInstanceId = null;
2304
+ if (xxCertificates[i].XPrivateKey) { privateKeyInstanceId = { 'InstanceID': xxCertificates[i].XPrivateKey['InstanceID'] }; }
2305
+ dev.certDeleteTasks++;
2306
+ dev.amtstack.Delete('AMT_PublicKeyCertificate', { 'InstanceID': xxCertificates[i]['InstanceID'] }, function (stack, name, response, status, tag) {
2307
+ if ((status == 200) && (tag != null)) {
2308
+ // If there is a private key, delete it.
2309
+ dev.amtstack.Delete('AMT_PublicPrivateKeyPair', tag, function () {
2310
+ if (--dev.certDeleteTasks == 0) { delete dev.certDeleteTasks; func(dev); }
2311
+ }, 0, 1);
2312
+ } else {
2313
+ if (--dev.certDeleteTasks == 0) { delete dev.certDeleteTasks; func(dev); }
2314
+ }
2315
+ }, privateKeyInstanceId);
2316
+ }
2317
+ }
2318
+ });
2319
+ }
2320
+
2321
+
2322
//
2323
// Intel AMT Hardware Inventory and Networking
2324
//