mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-10 13:23:41 +00:00
1003 lines
49 KiB
JavaScript
1003 lines
49 KiB
JavaScript
/*
|
|
Copyright 2018 - 2019 Intel Corporation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
var mei, lme;
|
|
var pthi, lms;
|
|
var realm;
|
|
var amt, transport, wsman;
|
|
var command;
|
|
var ERRORS = { JSON:65535, UnknownCommand:65534, UnknownResourceUri:65533, Pthi:65532, Lms:65531, Unknown:65530, ActivState:65529, Wsman:65528, Hbs:65527, Fetch:65526, Privileges:65525, NoParam:65524, NotAuthToken:65523 };
|
|
var comObject = new ComObjectInterop();
|
|
|
|
if (!isAdmin())
|
|
{
|
|
process.stdout.write('Error: Could not invoke amtcsp_engine.dll, system privileges are required.\n');
|
|
process.exit(ERRORS.Privileges);
|
|
}
|
|
|
|
if (process.argv.length == 1)
|
|
{
|
|
process.stdout.write('Usage: CSP [JSON-Value][-debug]\n');
|
|
process.stdout.write(' Example: CSP "{""Action"": ""GET"", ""ResourceUri"": ""DeviceInfo""}" -debug\n');
|
|
process.stdout.write(' Example: CSP "{""Action"": ""GET"", ""ResourceUri"": ""Settings/Configuration""}\n');
|
|
process.exit(ERRORS.NoParam);
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
command = JSON.parse(process.argv[1]);
|
|
console.log("Running command: '" + command.Action + "' on '" + command.ResourceUri + "'");
|
|
}
|
|
catch(e)
|
|
{
|
|
console.log('JSON Error');
|
|
comObject.dispatch({ErrorDescription: 'JSON Error - ' + e, ErrorCode: ERRORS.JSON});
|
|
process.exit(ERRORS.JSON);
|
|
}
|
|
|
|
process.on('uncaughtException', function onUncaughtException(e) { comObject.dispatch({ErrorDescription:'Unexpected Exception' + e, ErrorCode: ERRORS.Unknown}); process.exit(ERRORS.Unknown); }); // Something unexpected happened, so exit with '-1'
|
|
|
|
|
|
try
|
|
{
|
|
mei = require('amt-mei');
|
|
lme = require('amt-lme');
|
|
|
|
pthi = new mei();
|
|
pthi.on('error', function (e) { comObject.dispatch({ErrorDescription: 'Error during PTHI connection: ' + e, ErrorCode: ERRORS.Pthi}); process.exit(ERRORS.Pthi); });
|
|
|
|
lms = new lme();
|
|
lms.on('error', function (e)
|
|
{
|
|
if (e.errno && e.errno == 31)
|
|
{
|
|
// LMS already bound, so we can just ignore this
|
|
init();
|
|
}
|
|
else
|
|
{
|
|
comObject.dispatch({ ErrorDescription: 'Error during LMS connection: ' + e, ErrorCode: ERRORS.Lms });
|
|
process.exit(ERRORS.Lms);
|
|
}
|
|
});
|
|
lms.on('bind', function lmsOnBind(mapping) { if (mapping[16992]) { this.removeAllListeners('bind'); init(); } });
|
|
|
|
transport = require('amt-wsman-duk');
|
|
wsman = require('amt-wsman');
|
|
amt = require('amt');
|
|
}
|
|
catch (e)
|
|
{
|
|
comObject.dispatch({ErrorDescription: 'Error establishing PTHI connection: ' + e, ErrorCode: ERRORS.Unknown});
|
|
process.exit(ERRORS.Unknown); // could not establish PTHI connection
|
|
}
|
|
|
|
|
|
function init()
|
|
{
|
|
console.log('Getting AMT Realm...');
|
|
|
|
// Find the AMT Realm
|
|
this.cr = require('http').get('http://127.0.0.1:16992/wsman', function getRealmResponse(imsg)
|
|
{
|
|
if (imsg.statusCode == 401)
|
|
{
|
|
var tokens = imsg.headers['WWW-Authenticate'].split(',');
|
|
for (var i in tokens)
|
|
{
|
|
var token = tokens[i].split('=');
|
|
if(token[0].toUpperCase() == 'DIGEST REALM')
|
|
{
|
|
realm = token[1];
|
|
if (realm[0] == '"') { realm = realm.substring(1, realm.length - 1); }
|
|
console.log('AMT Realm is: ' + realm);
|
|
console.log('Getting LocalSystemAccount...');
|
|
|
|
// Get localSystemAccount
|
|
pthi.getLocalSystemAccount(function onGetLocalSystemAccount(x)
|
|
{
|
|
console.log('LocalSystemAccount = ' + x.user + ' / ' + x.pass);
|
|
if (command.AuthToken && command.Action.toUpperCase() == 'REPLACE' && command.ResourceUri == 'Settings/Activate')
|
|
{
|
|
pthi.wsstack = new wsman(transport, '127.0.0.1', 16992, x.user, x.pass, false);
|
|
console.log('AuthToken = ' + command.AuthToken);
|
|
console.log('Using Local OS/Admin');
|
|
}
|
|
else if (command.AuthToken)
|
|
{
|
|
console.log('AuthToken', command.AuthToken);
|
|
pthi.wsstack = new wsman({ transport: transport, host: '127.0.0.1', port: 16992, tls: false, authToken: command.AuthToken });
|
|
console.log('Using supplied AuthToken');
|
|
}
|
|
else
|
|
{
|
|
pthi.wsstack = new wsman(transport, '127.0.0.1', 16992, x.user, x.pass, false);
|
|
console.log('Using Local OS/Admin');
|
|
}
|
|
|
|
|
|
pthi.amtstack = new amt(pthi.wsstack);
|
|
run(); // Now we can actually start!
|
|
});
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function isAdmin()
|
|
{
|
|
var marshal = require('_GenericMarshal');
|
|
var AdvApi = marshal.CreateNativeProxy('Advapi32.dll');
|
|
AdvApi.CreateMethod('AllocateAndInitializeSid');
|
|
AdvApi.CreateMethod('CheckTokenMembership');
|
|
AdvApi.CreateMethod('FreeSid');
|
|
|
|
var NTAuthority = marshal.CreateVariable(6);
|
|
NTAuthority.toBuffer().writeInt8(5, 5);
|
|
var AdministratorsGroup = marshal.CreatePointer();
|
|
var admin = false;
|
|
|
|
if (AdvApi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0) {
|
|
var member = marshal.CreateInteger();
|
|
if (AdvApi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0) {
|
|
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
|
}
|
|
AdvApi.FreeSid(AdministratorsGroup.Deref());
|
|
}
|
|
return admin;
|
|
}
|
|
|
|
function run() {
|
|
switch (command.Action.toUpperCase()) {
|
|
case 'GET':
|
|
switch (command.ResourceUri) {
|
|
case 'Settings/ActivationState':
|
|
pthi.getControlMode(function (val) {
|
|
console.log('Current Control Mode ', val);
|
|
if (val.controlMode == undefined) {
|
|
comObject.dispatch({ ErrorDescription: 'Activation State Undefined', ErrorCode: ERRORS.ActivState });
|
|
process.exit(ERRORS.ActivState);
|
|
}
|
|
else {
|
|
comObject.dispatch(val.controlMode);
|
|
process.exit(0);
|
|
}
|
|
});
|
|
break;
|
|
case 'Settings/Certificates':
|
|
EnumerateCertificates(function OnEnumerateCerts(status, certs)
|
|
{
|
|
for(var i in certs)
|
|
{
|
|
console.log(certs[i]);
|
|
}
|
|
process.exit(0);
|
|
});
|
|
break;
|
|
case 'Settings/ConfigurationHash':
|
|
case 'Settings/Configuration':
|
|
var wsman_commands = "AMT_WebUIService,CIM_KVMRedirectionSAP,AMT_RedirectionService,AMT_EnvironmentDetectionSettingData,IPS_AlarmClockOccurrence,AMT_WiFiPortConfigurationService,AMT_TLSSettingData,AMT_PublicKeyCertificate".split(',');
|
|
|
|
pthi.amtstack.BatchEnum(null, wsman_commands, function getConfigurationResponse(stack, name, responses, status, arg) {
|
|
var WinCrypto = require('WinCrypto');
|
|
var config = {};
|
|
config.Redirection = {};
|
|
config.EnvironmentDetection = { DetectionStrings: [] };
|
|
config.AlarmClock = [];
|
|
config.TLS = {};
|
|
if (responses.AMT_WebUIService.responses.length > 0) {
|
|
config.WebUi = { State: (responses.AMT_WebUIService.responses[0].EnabledState == '2' || responses.AMT_WebUIService.responses[0].EnabledState == '6') ? 1 : 0 };
|
|
}
|
|
if (responses.CIM_KVMRedirectionSAP.responses.length > 0) {
|
|
config.Redirection.EnableKvm = (responses.CIM_KVMRedirectionSAP.responses[0].EnabledState == '2' || responses.CIM_KVMRedirectionSAP.responses[0].EnabledState == '6') ? 1 : 0;
|
|
}
|
|
if (responses.AMT_RedirectionService.responses.length > 0) {
|
|
var solider = parseInt(responses.AMT_RedirectionService.responses[0].EnabledState);
|
|
config.Redirection.EnableSol = (((solider & 32768) == 32768) && ((solider & 2) == 2)) ? 1 : 0;
|
|
config.Redirection.EnableStorage = (((solider & 32768) == 32768) && ((solider & 1) == 1)) ? 1 : 0;
|
|
}
|
|
|
|
if (responses.AMT_EnvironmentDetectionSettingData.responses.length > 0) { config.EnvironmentDetection.DetectionStrings = responses.AMT_EnvironmentDetectionSettingData.responses[0].DetectionStrings; }
|
|
if (responses.IPS_AlarmClockOccurrence.responses.length > 0) {
|
|
for (var i in responses.IPS_AlarmClockOccurrence.responses) {
|
|
if (responses.IPS_AlarmClockOccurrence.responses[i].StartTime) {
|
|
console.log('--> ', responses.IPS_AlarmClockOccurrence.responses[i]);
|
|
config.AlarmClock.push({ StartTime: responses.IPS_AlarmClockOccurrence.responses[i].StartTime, Interval: responses.IPS_AlarmClockOccurrence.responses[i].Interval });
|
|
}
|
|
}
|
|
}
|
|
|
|
if (responses.AMT_WiFiPortConfigurationService.responses.length > 0 && responses.AMT_WiFiPortConfigurationService.responses[0].localProfileSynchronizationEnabled != undefined)
|
|
{
|
|
config.WiFi = { AmtWiFiSync: parseInt(responses.AMT_WiFiPortConfigurationService.responses[0].localProfileSynchronizationEnabled) };
|
|
}
|
|
|
|
if (responses.AMT_TLSSettingData.responses.length > 0) {
|
|
config.TLS.Enabled = responses.AMT_TLSSettingData.responses[0].Enabled ? 1 : 0;
|
|
}
|
|
if (responses.AMT_PublicKeyCertificate.responses.length > 0) {
|
|
var x509 = Buffer.from(responses.AMT_PublicKeyCertificate.responses[0].X509Certificate, 'base64');
|
|
var pcert = WinCrypto.loadCert(x509, { encodingType: WinCrypto.X509_ASN_ENCODING });
|
|
config.TLS.Sha1Thumbprint = pcert.getInfo({ thumbprint: 'SHA1' }).thumbprint;
|
|
}
|
|
|
|
|
|
console.log('config.WebUi', config.WebUi);
|
|
console.log('config.Redirection', config.Redirection);
|
|
console.log('config.EnvironmentDetection', config.EnvironmentDetection);
|
|
console.log('config.AlarmClock', config.AlarmClock);
|
|
console.log('config.WiFi', config.WiFi ? config.WiFi : 'Not Supported');
|
|
console.log('config.TLS', config.TLS);
|
|
|
|
if (arg == 'Settings/ConfigurationHash')
|
|
{
|
|
pthi.amtstack.GetAuditLog(function OnConfigurationHash_GetAuditLog(statck, status, logs, cfg)
|
|
{
|
|
var lastProvisionTime = '';
|
|
if (status == 200)
|
|
{
|
|
for (var i in logs) {
|
|
if (logs[i].Event == 'Provisioning Started') {
|
|
lastProvisionTime = logs[i].Time;
|
|
}
|
|
}
|
|
}
|
|
console.log('GetAuditLog Status: ' + status);
|
|
console.log('Last Provisioning Time = ' + lastProvisionTime);
|
|
|
|
var configHash = require('SHA1Stream').create().syncHash(lastProvisionTime + ':' + JSON.stringify(config)).toString('hex');
|
|
console.log('SHA1 Hash = ' + configHash);
|
|
console.log('StdOut =>');
|
|
comObject.dispatch(configHash);
|
|
process.exit(0);
|
|
}, config);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
console.log('StdOut =>');
|
|
comObject.dispatch(config);
|
|
process.exit(0);
|
|
}
|
|
}, command.ResourceUri, true);
|
|
break;
|
|
case 'DeviceInfo':
|
|
this.smbios = require('smbios');
|
|
this.smbios.get(function onSMBiosGet(data) {
|
|
pthi.getVersion(function onGetVersion(version, self, smData) {
|
|
var amt = self.amtInfo(smData);
|
|
var sysInfo = self.systemInfo(smData);
|
|
var codeVersion = { BiosVersion: version.BiosVersion };
|
|
for (var vi in version.Versions) {
|
|
codeVersion[version.Versions[vi].Description] = version.Versions[vi].Version;
|
|
}
|
|
|
|
var devInfo = {};
|
|
devInfo.Device = {};
|
|
devInfo.Device.IntelPlatform = amt.AMT;
|
|
devInfo.Device.UUID = sysInfo.uuid;
|
|
|
|
// OSPrimaryDNSSuffix
|
|
var registry = require('windows_registry');
|
|
devInfo.Device.OSPrimaryDNSSuffix = registry.QueryKey(registry.HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters', 'Domain');
|
|
if (devInfo.Device.OSPrimaryDNSSuffix.length == 0) { delete devInfo.Device.OSPrimaryDNSSuffix; }
|
|
|
|
console.log('devInfo.Device', devInfo.Device);
|
|
|
|
devInfo.Me = {};
|
|
devInfo.Me.MeFwVersion = codeVersion.BiosVersion;
|
|
if ((codeVersion.Sku & 8) == 8) {
|
|
devInfo.Me.MeSku = 2;
|
|
}
|
|
else if ((codeVersion.Sku & 16) == 16) {
|
|
devInfo.Me.MeSku = 1;
|
|
}
|
|
else {
|
|
devInfo.Me.MeSku = 0;
|
|
}
|
|
|
|
|
|
devInfo.Me.DriverStatus = 0;
|
|
var Devices = require('DeviceManager').getDevices({ manufacturer: 'Intel*', class: 'System' });
|
|
for (var i in Devices) {
|
|
if (Devices[i].description.includes('Management Engine Interface')) {
|
|
devInfo.Me.DriverVersion = Devices[i].version;
|
|
switch (Devices[i].status) {
|
|
case 'ENABLED':
|
|
devInfo.Me.DriverStatus = 2;
|
|
break;
|
|
case 'DISABLED':
|
|
devInfo.Me.DriverStatus = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
console.log('devInfo.Me', devInfo.Me);
|
|
|
|
devInfo.Amt = {};
|
|
devInfo.Amt.DigestRealm = realm;
|
|
devInfo.Amt.AmtVersion = codeVersion.AMT;
|
|
devInfo.Amt.CcmEnabled = '';
|
|
devInfo.Amt.NetworkInterfaces = [];
|
|
// Type (0-Wired 1-Wireless)
|
|
// Status (0-Disabled 1-Enabled S0 2 - Enabled S0, Wake in Sx)
|
|
// IPv4Address (string)
|
|
//console.log('devInfo.Amt', devInfo.Amt);
|
|
|
|
var amtNics = [];
|
|
pthi.getLanInterfaceSettings(0, function (info, dv, nics) {
|
|
nics.push(info);
|
|
pthi.getLanInterfaceSettings(1, function (info, dv, nics) {
|
|
nics.push(info);
|
|
var n = require('os').networkInterfaces();
|
|
for (var nx in n) {
|
|
var intfc = n[nx];
|
|
for (var nxi in intfc) {
|
|
for (var infox in nics) {
|
|
if (intfc[nxi] && nics[infox]) {
|
|
if (intfc[nxi].mac == nics[infox].mac && intfc[nxi].family == 'IPv4')
|
|
{
|
|
console.log('OS => ' + intfc[nxi].address);
|
|
console.log('nics[' + infox + '] => ');
|
|
|
|
for (var z in nics[infox])
|
|
{
|
|
console.log(' [' + z + '] =>' + nics[infox][z]);
|
|
}
|
|
|
|
dv.Amt.NetworkInterfaces.push({ dnsSuffix: intfc[nxi].fqdn, type: (intfc[nxi].type == 'wireless' ? 1 : 0), Status: (nics[infox].enabled ? 1 : 0), IPv4Address: nics[infox].address });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
pthi.getControlMode(function onDeviceInfo_getControlMode(ccm, dev) {
|
|
dev.Amt.CcmEnabled = ccm.controlMode == 1 ? 1 : 0;
|
|
console.log('devInfo.Amt', dev.Amt);
|
|
|
|
for (var ii in dev.Amt.NetworkInterfaces) {
|
|
console.log('devInfo.Amt.NetworkInterfaces[' + ii + ']', dev.Amt.NetworkInterfaces[ii]);
|
|
}
|
|
console.log('Return value to StdOut =>');
|
|
comObject.dispatch(dev);
|
|
process.exit(0);
|
|
}, dv);
|
|
|
|
|
|
|
|
}, dv, nics);
|
|
}, devInfo, amtNics);
|
|
|
|
}, this, data);
|
|
});
|
|
break;
|
|
default:
|
|
comObject.dispatch({ ErrorDescription: 'Unknown ResourceUri', ErrorCode: ERRORS.UnknownResourceUri });
|
|
process.exit(ERRORS.UnknownResourceUri)
|
|
break;
|
|
}
|
|
break;
|
|
case 'DELETE':
|
|
switch (command.ResourceUri) {
|
|
case 'Settings/Activate':
|
|
pthi.unprovision(1, function unprovisionResponse(status) { console.log('Unprovision', status); process.exit(status); });
|
|
break;
|
|
default:
|
|
comObject.dispatch({ ErrorDescription: 'Unknown ResourceUri', ErrorCode: ERRORS.UnknownResourceUri });
|
|
process.exit(ERRORS.UnknownResourceUri);
|
|
break;
|
|
}
|
|
break;
|
|
case 'REPLACE':
|
|
switch (command.ResourceUri)
|
|
{
|
|
case 'Settings/Configuration':
|
|
if (command.AuthToken == undefined || command.AuthToken == '') {
|
|
comObject.dispatch({ ErrorDescription: 'Access Denied: AuthToken not included.', ErrorCode: ERRORS.NotAuthToken });
|
|
process.exit(ERRORS.NotAuthToken);
|
|
}
|
|
var wsman_commands = "AMT_WebUIService,CIM_KVMRedirectionSAP,AMT_RedirectionService,AMT_EnvironmentDetectionSettingData,IPS_AlarmClockOccurrence,AMT_WiFiPortConfigurationService,AMT_TLSSettingData,AMT_TLSCredentialContext,".split(',');
|
|
pthi.amtstack.BatchEnum(null, wsman_commands, function replaceResponse1(stack, name, responses, status, arg) {
|
|
NextReplace(responses);
|
|
}, command, true);
|
|
break;
|
|
case 'Settings/Activate':
|
|
if (command.ActivationState <= 0)
|
|
{
|
|
console.log('Bad ActivationState: ' + command.ActivationState);
|
|
comObject.dispatch({ ErrorDescription: 'Bad ActivationState: ' + command.ActivationState, ErrorCode: ERRORS.ActivState });
|
|
process.exit(ERRORS.ActivState);
|
|
}
|
|
if (command.RequestedStateChange == null || command.RequestedStateChange != 1)
|
|
{
|
|
console.log('Bad RequestedStateChange: ' + command.RequestedStateChange);
|
|
comObject.dispatch({ ErrorDescription: 'Bad RequestedStateChange: ' + command.RequestedStateChange, ErrorCode: ERRORS.ActivState });
|
|
process.exit(ERRORS.ActivState);
|
|
}
|
|
pthi.amtstack.BatchEnum(null, ['*IPS_HostBasedSetupService'], function ccmActivate_Response1(stack, name, responses, status, arg) {
|
|
if (status != 200) {
|
|
if (status == 600) {
|
|
console.log('WSMAN Internal Error: ' + status);
|
|
comObject.dispatch({ ErrorDescription: 'WSMAN Internal Error: ' + status, ErrorCode: ERRORS.Wsman });
|
|
}
|
|
else {
|
|
console.log('WSMAN HTTP Error code: ' + status);
|
|
comObject.dispatch({ ErrorDescription: 'WSMAN HTTP Error code: ' + status, ErrorCode: ERRORS.Wsman });
|
|
}
|
|
process.exit(ERRORS.Wsman);
|
|
}
|
|
else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) {
|
|
console.log('Received invalid WSMAN response');
|
|
comObject.dispatch({ ErrorDescription: 'Received invalid WSMAN response', ErrorCode: ERRORS.Wsman });
|
|
process.exit(ERRORS.Wsman);
|
|
}
|
|
else {
|
|
pthi.amtstack.IPS_HostBasedSetupService_Setup(2, command.Payload.AuthToken, null, null, null, null, function ccmActivate_Response2(stack, name, responses, status, args) {
|
|
if (status != 200) {
|
|
console.log('HostBasedSetup returned HTTP error code: ' + status);
|
|
comObject.dispatch({ ErrorDescription: 'HostBasedSetup returned HTTP error code: ' + status, ErrorCode: ERRORS.Hbs });
|
|
process.exit(ERRORS.Hbs);
|
|
}
|
|
else if (responses.Body.ReturnValue != 0) {
|
|
var HbsRetVals = ['SUCCESS', 'INTERNAL ERROR', 'INVALID STATE', 'INVALID PARAM', 'METHOD DISABLED', 'AUTH_FAILED', 'FLASH_WRITE_LIMIT_EXCEEDED'];
|
|
if (responses.Body.ReturnValue > 0 && responses.Body.ReturnValue < 7) {
|
|
console.log('IPS_HostBasedSetupService returned: ' + HbsRetVals[responses.Body.ReturnValue] + ' (' + responses.Body.ReturnValue + ')');
|
|
comObject.dispatch({ ErrorDescription: 'IPS_HostBasedSetupService returned: ' + HbsRetVals[responses.Body.ReturnValue] + ' (' + responses.Body.ReturnValue + ')', ErrorCode: ERRORS.Hbs });
|
|
}
|
|
else {
|
|
console.log('IPS_HostBasedSetupService returned a Unknown status (' + responses.Body.ReturnValue + ')');
|
|
comObject.dispatch({ ErrorDescription: 'IPS_HostBasedSetupService returned a Unknown status (' + responses.Body.ReturnValue + ')', ErrorCode: ERRORS.Hbs });
|
|
}
|
|
process.exit(ERRORS.Hbs);
|
|
}
|
|
else { console.log('Provisioned in CCM'); process.exit(0); }
|
|
}, arg);
|
|
}
|
|
}, { AuthToken: command.Payload.AuthToken, RequestedStateChange: command.Payload.RequestedStateChange, pwd: command.pwd });
|
|
break;
|
|
default:
|
|
comObject.dispatch({ ErrorDescription: 'Unknown ResourceUri', ErrorCode: ERRORS.UnknownResourceUri });
|
|
process.exit(ERRORS.UnknownResourceUri);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
comObject.dispatch({ ErrorDescription: 'Unknown ResourceCommand', ErrorCode: ERRORS.UnknownCommand });
|
|
process.exit(ERRORS.UnknownCommand);
|
|
break;
|
|
}
|
|
|
|
function NextReplaceResults(action, status) {
|
|
if (status == 200) {
|
|
--pthi.amtstack.ReplaceCounter;
|
|
if (pthi.amtstack.ReplaceCounter == 0) {
|
|
console.log('Success');
|
|
process.exit(0);
|
|
}
|
|
}
|
|
else {
|
|
console.log('Error Replacing: ' + action + ' [' + status + ']');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
function NextReplace(responses) {
|
|
pthi.amtstack.ReplaceCounter = 0;
|
|
|
|
if (command.Payload.WiFi) {
|
|
if (responses.AMT_WiFiPortConfigurationService && responses.AMT_WiFiPortConfigurationService.responses.length > 0)
|
|
{
|
|
++pthi.amtstack.ReplaceCounter;
|
|
responses.AMT_WiFiPortConfigurationService.responses[0].localProfileSynchronizationEnabled = command.Payload.WiFi.AmtWiFiSync ? 1 : 0;
|
|
pthi.amtstack.Put('AMT_WiFiPortConfigurationService', responses.AMT_WiFiPortConfigurationService.responses[0], function replaceResponse2_wifi(xstack, xname, xresponse, xstatus, xtag) {
|
|
NextReplaceResults('WiFi', xstatus);
|
|
}, responses)
|
|
}
|
|
else
|
|
{
|
|
++pthi.amtstack.ReplaceCounter;
|
|
AMT_SupportsWireless(function OnWirelessCheck(supported)
|
|
{
|
|
if(supported)
|
|
{
|
|
console.log('[WiFi] Error Fetching State');
|
|
comObject.dispatch({ ErrorDescription: '[WiFi] Error Fetching State', ErrorCode: ERRORS.Fetch });
|
|
process.exit(ERRORS.Fetch);
|
|
}
|
|
else
|
|
{
|
|
NextReplaceResults('WiFi', 200);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
if (command.Payload.WebUi) {
|
|
if (responses.AMT_WebUIService && responses.AMT_WebUIService.responses.length > 0) {
|
|
++pthi.amtstack.ReplaceCounter;
|
|
pthi.amtstack.AMT_WebUIService_RequestStateChange(command.Payload.WebUi.State == 0 ? 3 : 2, null, function webUiStateChangeRequestSink(xstack, xname, xresponse, xstatus, xtag) {
|
|
NextReplaceResults('WebUi', xstatus);
|
|
});
|
|
}
|
|
else {
|
|
console.log('[WebUI] Error Fetching State');
|
|
comObject.dispatch({ ErrorDescription: '[WebUI] Error Fetching State', ErrorCode: ERRORS.Fetch });
|
|
process.exit(ERRORS.Fetch);
|
|
}
|
|
}
|
|
if (command.Payload.Redirection) {
|
|
if (command.Payload.Redirection.EnableSol != undefined || command.Payload.Redirection.EnableStorage != undefined) {
|
|
++pthi.amtstack.ReplaceCounter;
|
|
var mask = 32768;
|
|
if (command.Payload.Redirection.EnableSol) { mask |= 2; }
|
|
if (command.Payload.Redirection.EnableStorage) { mask |= 1; }
|
|
|
|
pthi.amtstack.AMT_RedirectionService_RequestStateChange(mask, function redirectionOnRequestedStateChange(xstack, xname, xresponse, xstatus, xtag) {
|
|
NextReplaceResults('Redirection/SOL/IDER', xstatus);
|
|
});
|
|
}
|
|
if (command.Payload.Redirection.EnableKvm != undefined) {
|
|
++pthi.amtstack.ReplaceCounter;
|
|
pthi.amtstack.CIM_KVMRedirectionSAP_RequestStateChange(command.Payload.Redirection.EnableKvm ? 2 : 3, 0, function redirectionOnKvmRequestStateChange(xstack, xname, xresponse, xstatus, xtag) {
|
|
NextReplaceResults('Redirection/Kvm', xstatus);
|
|
});
|
|
}
|
|
}
|
|
if (command.Payload.TLS != undefined) {
|
|
console.log('TLS', command.Payload.TLS);
|
|
console.log('Counter', pthi.amtstack.ReplaceCounter);
|
|
if (command.Payload.TLS.Enabled == false || command.Payload.TLS.Enabled == 0) {
|
|
console.log(' Disabling TLS');
|
|
if (responses.AMT_TLSSettingData && responses.AMT_TLSSettingData.responses.length > 0) {
|
|
if (responses.AMT_TLSCredentialContext && responses.AMT_TLSCredentialContext.responses.length > 0)
|
|
{
|
|
// TLS is Currently Set
|
|
for (var i in responses.AMT_TLSSettingData.responses) {
|
|
++pthi.amtstack.ReplaceCounter;
|
|
var setting = JSON.parse(JSON.stringify(responses.AMT_TLSSettingData.responses[i]));
|
|
setting.Enabled = false;
|
|
|
|
console.log(i, setting);
|
|
pthi.amtstack.Put('AMT_TLSSettingData', setting, function replaceResponse2_tls(xstack, xname, xresponse, xstatus, xtag) {
|
|
console.log('xstatus=' + xstatus);
|
|
NextReplaceResults('TLS', xstatus);
|
|
}, 0, 1, setting);
|
|
}
|
|
++pthi.amtstack.ReplaceCounter;
|
|
pthi.amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, function onTlsCommitchanges(xstack, xname, xresponse, xstatus, xtag)
|
|
{
|
|
if (xstatus != 200) {
|
|
NextReplaceResults('TLS-Commit-Change', xstatus);
|
|
}
|
|
else {
|
|
// Set a timeout, and try this in 2 seconds, because AMT has a bug, where if you try to delete a cert too fast, it will fail
|
|
console.log('Setting 2 second delay, before attempting to delete TLS Certificate...');
|
|
pthi.amtstack._tlsTimeout = setTimeout(function tlsDeleteCredential_wait(credential)
|
|
{
|
|
EnumerateCertificates(function onEnumerateCerts(xstatus, xcerts, xcredential)
|
|
{
|
|
if (xstatus != 200) { NextReplaceResults('TLS-Enumerate-Certificates', xstatus); return; }
|
|
for(var i in xcerts)
|
|
{
|
|
if(xcerts[i].isTlsCertificate && xcerts[i].privateKeyInstanceID)
|
|
{
|
|
xcerts[i].Delete(function OnDelete(xxstatus)
|
|
{
|
|
NextReplaceResults('TLS-Disable', xxstatus);
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}, credential);
|
|
}, 2000, xtag);
|
|
}
|
|
}, JSON.parse(JSON.stringify(responses.AMT_TLSCredentialContext.responses[0])));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Before we can enable TLS, we have to issue a certificate
|
|
IssueSelfSignedCertificate();
|
|
}
|
|
}
|
|
|
|
|
|
if (command.Payload.AlarmClock) {
|
|
console.log('command.Payload.AlarmClock', command.Payload.AlarmClock);
|
|
|
|
if (responses.IPS_AlarmClockOccurrence && responses.IPS_AlarmClockOccurrence.responses.length > 0) {
|
|
// If there are any existing
|
|
for (var i in responses.IPS_AlarmClockOccurrence.responses) {
|
|
console.log('==> Deleting AlarmClock Occurrence');
|
|
++pthi.amtstack.ReplaceCounter;
|
|
pthi.amtstack.Delete('IPS_AlarmClockOccurrence', responses.IPS_AlarmClockOccurrence.responses[i], function onAlarmClockDelete(xstack, xname, xresponse, xstatus, xtag) {
|
|
NextReplaceResults('AlarmClock_Delete', xstatus);
|
|
});
|
|
}
|
|
}
|
|
for (var i in command.Payload.AlarmClock) {
|
|
++pthi.amtstack.ReplaceCounter;
|
|
var alarmClockInstance = { StartTime: { Datetime: command.Payload.AlarmClock[i].StartTime }, DeleteOnCompletion: true };
|
|
alarmClockInstance.ElementName = ('Alarm' + i);
|
|
alarmClockInstance.InstanceID = ('Alarm' + i);
|
|
if (command.Payload.AlarmClock[i].Interval) {
|
|
alarmClockInstance.Interval = { Datetime: command.Payload.AlarmClock[i].Interval };
|
|
}
|
|
pthi.amtstack.AMT_AlarmClockService_AddAlarm(alarmClockInstance, function onAlarmClockAddAlarm(xstack, xname, xresponse, xstatus, xtag) {
|
|
NextReplaceResults('AlarmClock_AddAlarm', xstatus);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function IssueSelfSignedCertificate() {
|
|
++pthi.amtstack.ReplaceCounter;
|
|
pthi.amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, function onIssueSelfSignedCertificate(stack, serviceName, response, status) {
|
|
if (status != 200) {
|
|
NextReplaceResults('AMT_PublicKeyManagementService_GenerateKeyPair (Too Soon?)', xstatus);
|
|
}
|
|
else {
|
|
if (response.Body['ReturnValue'] != 0) { NextReplaceResults('AMT_PublicKeyManagementService_GenerateKeyPair: ' + response.Body['ReturnValueStr'], 600); return; }
|
|
|
|
// Get the new key pair
|
|
pthi.amtstack.Enum('AMT_PublicPrivateKeyPair', function onFetchPublicPrivateKeyPair(stack, serviceName, response, status, tag) {
|
|
if (status != 200) {
|
|
NextReplaceResults('AMT_PublicPrivateKeyPair', xstatus);
|
|
}
|
|
else {
|
|
var DERKey = null;
|
|
for (var i in response) { if (response[i]['InstanceID'] == tag) DERKey = response[i]['DERKey']; }
|
|
|
|
var WinCrypto = require('WinCrypto');
|
|
var options =
|
|
{
|
|
_algorithm: 'SHA256',
|
|
_years: 10,
|
|
CN: 'UntrustedRoot',
|
|
T: 'UntrustedCert',
|
|
O: 'Intel',
|
|
C: 'USA',
|
|
ST: 'CA'
|
|
};
|
|
console.log(' Generating Dummy Root Certificate');
|
|
var untrustedRoot = WinCrypto.makeCert(options);
|
|
|
|
var AmtPublicKey = Buffer.from(DERKey, 'base64');
|
|
AmtPublicKey.oid = WinCrypto.CRYPT_KEY_ALGORITHMS_OIDS['RSA_RSA'];
|
|
|
|
console.log(' Using AMT Public Key to generate Certificate');
|
|
var child = WinCrypto.MakeCertFromPublicKey(
|
|
{
|
|
Issuer: 'CN=UntrustedRoot', Subject: { CN: 'SelfSigned', ST: 'CA', O: 'Intel', C: 'USA', T: 'SelfSignedCert' }, PublicKey: AmtPublicKey, SigningCert: untrustedRoot, SignatureAlgorithm: WinCrypto.CRYPT_KEY_ALGORITHMS_OIDS['RSA_SHA256RSA'],
|
|
EnhancedKeyUsages: [WinCrypto.CRYPT_ENHANCED_KEY_USAGES.SERVER_AUTH],
|
|
KeyUsage: ['CERT_DATA_ENCIPHERMENT_KEY_USAGE', 'CERT_DIGITAL_SIGNATURE_KEY_USAGE', 'CERT_KEY_ENCIPHERMENT_KEY_USAGE', 'CERT_NON_REPUDIATION_KEY_USAGE', 'CERT_KEY_CERT_SIGN_KEY_USAGE']
|
|
});
|
|
|
|
console.log(' Signing certificate with dummy root');
|
|
var signedCert = WinCrypto.SignCertificate(untrustedRoot, child);
|
|
signedCert.blob = signedCert.toBuffer().toString('base64');
|
|
|
|
pthi.amtstack.AMT_PublicKeyManagementService_AddCertificate(signedCert.blob, function onAddCertificate(stack, serviceName, response, status, tag) {
|
|
if (status != 200) {
|
|
NextReplaceResults('AMT_PublicKeyManagementService_AddCertificate', status);
|
|
}
|
|
else {
|
|
SetupTLS(response);
|
|
}
|
|
}, signedCert.blob);
|
|
}
|
|
}, response.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']);
|
|
}
|
|
});
|
|
}
|
|
function SetupTLS(response) {
|
|
console.log('fetching AMT_TLSProtocolEndpointCollection');
|
|
pthi.amtstack.BatchEnum(null, ['AMT_TLSProtocolEndpointCollection'], function onEnableTLS_getCollection(stack, name, responses, status, xtag) {
|
|
if (status != 200) {
|
|
NextReplaceResults('AMT_TLSProtocolEndpointCollection', status);
|
|
}
|
|
else {
|
|
XmlObjToXmlObj(xtag.Body.CreatedCertificate);
|
|
|
|
var _certificate =
|
|
{
|
|
'a:Address': { Value: '/wsman' },
|
|
'a:ReferenceParameters': {
|
|
Value:
|
|
{
|
|
'w:ResourceURI': { Value: 'http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate' },
|
|
'w:SelectorSet': { Value: { 'w:Selector': { '@Name': 'InstanceID', Value: xtag.Body.CreatedCertificate.ReferenceParameters.Value.SelectorSet.Value.Selector.Value } } }
|
|
}
|
|
}
|
|
};
|
|
|
|
var CreatedCertificate = ObjToXml(_certificate);
|
|
var _provider =
|
|
{
|
|
'a:Address': { Value: '/wsman' },
|
|
'a:ReferenceParameters': {
|
|
Value: {
|
|
'w:ResourceURI': { Value: 'http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TLSProtocolEndpointCollection' },
|
|
'w:SelectorSet': { Value: { 'w:Selector': { '@Name': 'ElementName', Value: 'TLSProtocolEndpointInstances Collection' } } }
|
|
}
|
|
}
|
|
};
|
|
|
|
var Provider = ObjToXml(_provider);
|
|
|
|
pthi.amtstack.AMT_TLSCredentialContext_Create(CreatedCertificate, Provider, function onEnableTLS_createContext(xstack, xname, xresponses, xstatus, xtag) {
|
|
if (xstatus != 200) {
|
|
NextReplaceResults('AMT_TLSCredentialContext_Create', xstatus);
|
|
}
|
|
else {
|
|
pthi.amtstack.BatchEnum(null, ['AMT_TLSSettingData'], function onCreateTLSCredentialContext_GetTLSSettingsData(xstack, xname, responses, xstatus, xarg) {
|
|
if (xstatus != 200) {
|
|
NextReplaceResults('AMT_TLSSettingData', xstatus);
|
|
}
|
|
else {
|
|
EnableTLS(responses.AMT_TLSSettingData);
|
|
}
|
|
}, null, true);
|
|
}
|
|
|
|
});
|
|
}
|
|
}, response, true);
|
|
}
|
|
function EnableTLS(AMT_TLSSettingData)
|
|
{
|
|
if (AMT_TLSSettingData && AMT_TLSSettingData.responses.length > 0)
|
|
{
|
|
for (var i in AMT_TLSSettingData.responses)
|
|
{
|
|
var setting = JSON.parse(JSON.stringify(AMT_TLSSettingData.responses[i]));
|
|
setting.Enabled = true;
|
|
setting.AcceptNonSecureConnections = true;
|
|
setting.MutualAuthentication = false;
|
|
|
|
pthi.amtstack.Put('AMT_TLSSettingData', setting, function (xstack, xname, xresponse, xstatus, xtag)
|
|
{
|
|
if (xstatus != 200)
|
|
{
|
|
NextReplaceResults('AMT_TLSSettingData', xstatus);
|
|
}
|
|
}, 0, 1, setting);
|
|
}
|
|
pthi.amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, function (xstack, xname, xresponse, xstatus, xtag)
|
|
{
|
|
NextReplaceResults('TLS-Commit-Change', xstatus);
|
|
});
|
|
}
|
|
}
|
|
function EnumerateCertificates(callback_func)
|
|
{
|
|
var tag = [];
|
|
for(var i in arguments) {tag.push(arguments[i]);}
|
|
|
|
pthi.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', 'AMT_TLSCredentialContext', 'AMT_PublicPrivateKeyPair'], function onEnumerateCertificates(stack, name, responses, status, xtag)
|
|
{
|
|
if (status != 200) { var cb = xtag.shift(); xtag.unshift([]); xtag.unshift(status); cb.apply(null, xtag); return; }
|
|
var WinCrypto = require('WinCrypto');
|
|
var certs = [];
|
|
|
|
if(responses.AMT_PublicKeyCertificate && responses.AMT_PublicKeyCertificate.responses.length>0)
|
|
{
|
|
for(var i in responses.AMT_PublicKeyCertificate.responses)
|
|
{
|
|
var cert = responses.AMT_PublicKeyCertificate.responses[i];
|
|
var x509 = Buffer.from(cert.X509Certificate, 'base64');
|
|
var _cert = WinCrypto.loadCert(x509, { encodingType: WinCrypto.X509_ASN_ENCODING });
|
|
var _info = _cert.getInfo();
|
|
certs.push(cert);
|
|
|
|
cert.Delete = Certificate_Delete;
|
|
|
|
if(responses.AMT_PublicPrivateKeyPair && responses.AMT_PublicPrivateKeyPair.responses.length>0)
|
|
{
|
|
for(var x in responses.AMT_PublicPrivateKeyPair.responses)
|
|
{
|
|
if ((cert.hasPrivateKey = responses.AMT_PublicPrivateKeyPair.responses[x]['DERKey'] == _info.publicKey))
|
|
{
|
|
cert.privateKeyInstanceID = responses.AMT_PublicPrivateKeyPair.responses[x]['InstanceID']
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(responses.AMT_TLSCredentialContext && responses.AMT_TLSCredentialContext.responses.length>0)
|
|
{
|
|
for(var x in responses.AMT_TLSCredentialContext.responses)
|
|
{
|
|
if ((cert.isTlsCertificate = responses.AMT_TLSCredentialContext.responses[x].ElementInContext.ReferenceParameters.SelectorSet.Selector.Value == cert.InstanceID))
|
|
{
|
|
cert.tlsCredentialContext = JSON.parse(JSON.stringify(responses.AMT_TLSCredentialContext.responses[x]));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var cb = xtag.shift();
|
|
xtag.unshift(certs);
|
|
xtag.unshift(status);
|
|
cb.apply(null, xtag);
|
|
}, tag, true);
|
|
}
|
|
}
|
|
|
|
function ComObjectInterop()
|
|
{
|
|
this._ObjectID = 'ComObjectInterop';
|
|
this._marshal = require('_GenericMarshal');
|
|
this._native = this._marshal.CreateNativeProxy();
|
|
|
|
console.setDestination(console.Destinations.DISABLED);
|
|
for (var i in process.argv) {
|
|
if (process.argv[i] == '-debug') {
|
|
console.setDestination(console.Destinations.STDOUT);
|
|
break;
|
|
}
|
|
}
|
|
|
|
try {
|
|
this._native.CreateMethod({ method: 'ExternalDispatchSink', dereferencePointer: 1 });
|
|
this.dispatch = function dispatch(obj) { this._native.ExternalDispatchSink(this._marshal.CreateVariable(JSON.stringify(obj))); };
|
|
}
|
|
catch (e) {
|
|
this.dispatch = function dispatch(obj) { process.stdout.write(JSON.stringify(obj)); }
|
|
}
|
|
}
|
|
function XmlObjToXmlObj(j)
|
|
{
|
|
var inlineValue = false;
|
|
for (var i in j)
|
|
{
|
|
if(typeof(j[i]=='object'))
|
|
{
|
|
if(j[i].Value == null)
|
|
{
|
|
var tmp = { Value: j[i] };
|
|
j[i] = tmp;
|
|
}
|
|
XmlObjToXmlObj(j[i].Value);
|
|
}
|
|
else
|
|
{
|
|
var tmp = { Value: j[i] };
|
|
j[i] = tmp;
|
|
}
|
|
}
|
|
}
|
|
function ObjToXml(key, value)
|
|
{
|
|
if (arguments.length == 1 && typeof (key) == 'object')
|
|
{
|
|
retVal = '';
|
|
for(var i in key)
|
|
{
|
|
retVal += ObjToXml(i, key[i]);
|
|
}
|
|
return (retVal);
|
|
}
|
|
|
|
var retVal = '<' + key;
|
|
var attr = false;
|
|
for (var i in value)
|
|
{
|
|
if(i.startsWith('@'))
|
|
{
|
|
retVal += (' ' + i.substring(1) + '="' + value[i] + '"'); attr = true;
|
|
}
|
|
}
|
|
retVal += ((attr ? ' ' : '') + '>');
|
|
|
|
if (value.Value) { retVal += (typeof (value.Value) == 'string' ? value.Value : ObjToXml(value.Value)); }
|
|
retVal += ('</' + key + '>');
|
|
|
|
return (retVal);
|
|
}
|
|
|
|
function Certificate_Delete(callback_func)
|
|
{
|
|
var tag = [this];
|
|
for (var i in arguments) { tag.push(arguments[i]); }
|
|
|
|
// First Step is to delete TLSCredentialContext if it exists
|
|
if(this.tlsCredentialContext)
|
|
{
|
|
console.log('Deleting TLSCredentialContext');
|
|
pthi.amtstack.Delete('AMT_TLSCredentialContext', this.tlsCredentialContext, function onDeleteTLSCredentialContext(xstack, xname, xresponse, xstatus, xtag)
|
|
{
|
|
if (xstatus != 200)
|
|
{
|
|
var self = xtag.shift();
|
|
var cb = xtag.shift();
|
|
xtag.unshift(xstatus);
|
|
cb.apply(self, xtag);
|
|
}
|
|
else
|
|
{
|
|
Certificate_Delete_2.call(xtag[0], xtag);
|
|
}
|
|
}, tag);
|
|
}
|
|
else
|
|
{
|
|
Certificate_Delete_2.call(xtag[0], xtag);
|
|
}
|
|
}
|
|
function Certificate_Delete_2(xtag)
|
|
{
|
|
// Check if there is a private key
|
|
if(this.hasPrivateKey && this.privateKeyInstanceID)
|
|
{
|
|
console.log('Deleting Public/Private Key Pair: [' + this.privateKeyInstanceID + ']');
|
|
var sset = { InstanceID: this.privateKeyInstanceID };
|
|
pthi.amtstack.Delete('AMT_PublicPrivateKeyPair', sset, function onCertificate_Delete_2(xstack, xname, xresponse, xstatus, xxtag)
|
|
{
|
|
if (xstatus != 200)
|
|
{
|
|
var self = xxtag.shift();
|
|
var cb = xxtag.shift();
|
|
xxtag.unshift(xstatus);
|
|
cb.apply(self, xxtag);
|
|
}
|
|
else
|
|
{
|
|
Certificate_Delete_3.call(xxtag[0], xxtag);
|
|
}
|
|
}, xtag);
|
|
}
|
|
else
|
|
{
|
|
Certificate_Delete_3.call(xtag[0], xtag);
|
|
}
|
|
}
|
|
function Certificate_Delete_3(xtag)
|
|
{
|
|
// Delete the Certificate
|
|
console.log('Deleting Certificate: [' + this.InstanceID + ']');
|
|
var sset = { InstanceID: this.InstanceID };
|
|
pthi.amtstack.Delete('AMT_PublicKeyCertificate', sset, function onCertificate_Delete_3(xstack, xname, xresponse, xstatus, xxtag)
|
|
{
|
|
var self = xxtag.shift();
|
|
var cb = xxtag.shift();
|
|
xxtag.unshift(xstatus);
|
|
cb.apply(self, xxtag);
|
|
}, xtag);
|
|
}
|
|
|
|
function AMT_SupportsWireless(func_callback)
|
|
{
|
|
var opt = [];
|
|
for (var i in arguments) { opt.push(arguments[i]); }
|
|
|
|
pthi.getLanInterfaceSettings(1, function onAMTSupportsWireless(info, tag)
|
|
{
|
|
var cb = tag.shift();
|
|
tag.unshift(info != null);
|
|
cb.apply(null, tag);
|
|
}, opt);
|
|
} |