2Copyright 2018-2021 Intel Corporation
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
18* @fileoverview Intel(r) AMT Management
19* @author Ylian Saint-Hilaire
24 * Construct a AmtStackCreateService object, this ia the main Intel AMT communication stack.
27function AmtManager(agent, db, isdebug) {
28 var sendConsole = function (msg) { agent.SendCommand({ 'action': 'msg', 'type': 'console', 'value': msg }); }
29 var debug = function (msg) { if (isdebug) { sendConsole('amt-manager: ' + msg + '<br />'); } }
30 var amtMei = null, amtMeiState = 0;
31 var amtLms = null, amtLmsState = 0;
32 var amtGetVersionResult = null;
35 var trustedHashes = null;;
37 require('events').EventEmitter.call(obj, true)
38 .createEvent('stateChange_LMS')
39 .createEvent('portBinding_LMS');
43 obj.on('newListener', function (name, callback) {
44 if (name == 'portBinding_LMS') { callback.call(this, this._mapping); }
47 Object.defineProperty(obj, 'lmsstate',
49 get: function () { return (this._lmsstate); },
50 set: function (value) { if (this._lmsstate != value) { this._lmsstate = value; this.emit('stateChange_LMS', value); } }
54 obj.onStateChange = null;
55 obj.setDebug = function (x) { isdebug = x; }
57 // Try to load up the MEI module
58 var rebindToMeiRetrys = 0;
59 obj.reset = function () {
61 obj.amtMei = null, amtMei = null, amtMeiState = 0, amtLms = null, amtLmsState = 0, obj.state = 0, obj.lmsstate = 0;
62 //debug('Binding to MEI');
64 var amtMeiLib = require('amt-mei');
65 obj.amtMei = amtMei = new amtMeiLib();
66 amtMei.on('error', function (e) { debug('MEI error'); amtMei = null; amtMeiState = -1; obj.state = -1; if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); } });
67 amtMei.getVersion(function (result) {
69 obj.state = amtMeiState = -1;
70 if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
71 if (rebindToMeiRetrys < 10) { setTimeout(obj.reset, 10000); }
73 amtGetVersionResult = result;
74 obj.state = amtMeiState = 2;
75 rebindToMeiRetrys = 0;
76 if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
77 //debug('MEI binded');
81 } catch (ex) { debug("MEI exception: " + ex); amtMei = null; amtMeiState = -1; obj.state = -1; }
84 // Get Intel MEI State in a flexible way
85 // Flags: 1 = Versions, 2 = OsAdmin, 4 = Hashes, 8 = Network
86 var getMeiStateCache = {}; // Some MEI calls will only be made once and cached here.
87 obj.getMeiState = function(flags, func) {
88 if ((amtMei == null) || (amtMeiState < 2)) { if (func != null) { func(null); } return; }
90 var amtMeiTmpState = { 'core-ver': 1, OsHostname: require('os').hostname(), Flags: 0 }; // Flags: 1=EHBC, 2=CCM, 4=ACM
91 if (getMeiStateCache.MeiVersion != null) { amtMeiTmpState.MeiVersion = getMeiStateCache.MeiVersion; } else { amtMei.getProtocolVersion(function (result) { if (result != null) { getMeiStateCache.MeiVersion = amtMeiTmpState.MeiVersion = result; } }); }
92 if ((flags & 1) != 0) {
93 if (getMeiStateCache.Versions != null) {
94 amtMeiTmpState.Versions = getMeiStateCache.Versions;
96 amtMei.getVersion(function (result) { if (result) { getMeiStateCache.Versions = amtMeiTmpState.Versions = {}; for (var version in result.Versions) { amtMeiTmpState.Versions[result.Versions[version].Description] = result.Versions[version].Version; } } });
99 amtMei.getProvisioningMode(function (result) { if (result) { amtMeiTmpState.ProvisioningMode = result.mode; } });
100 amtMei.getProvisioningState(function (result) { if (result) { amtMeiTmpState.ProvisioningState = result.state; if (result.state != 2) { amtMei.stopConfiguration(function () { }); } } }); // 0: "Not Activated (Pre)", 1: "Not Activated (In)", 2: "Activated". Make sure to stop remote configuration if needed.
101 amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } });
102 amtMei.getControlMode(function (result) { if (result != null) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } } }); // Flag 2 = CCM, 4 = ACM
103 //amtMei.getMACAddresses(function (result) { if (result) { amtMeiTmpState.mac = result; } });
104 if ((flags & 8) != 0) {
105 amtMei.getLanInterfaceSettings(0, function (result) {
107 amtMeiTmpState.net0 = result;
108 var fqdn = null, interfaces = require('os').networkInterfaces(); // Look for the DNS suffix for the Intel AMT Ethernet interface
109 for (var i in interfaces) { for (var j in interfaces[i]) { if ((interfaces[i][j].mac == result.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { amtMeiTmpState.OsDnsSuffix = interfaces[i][j].fqdn; } } }
112 amtMei.getLanInterfaceSettings(1, function (result) { if (result) { amtMeiTmpState.net1 = result; } });
114 if (getMeiStateCache.UUID != null) { amtMeiTmpState.UUID = getMeiStateCache.UUID; } else { amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { getMeiStateCache.UUID = amtMeiTmpState.UUID = result.uuid; } }); }
115 if ((flags & 2) != 0) { amtMei.getLocalSystemAccount(function (x) { if ((x != null) && x.user && x.pass) { amtMeiTmpState.OsAdmin = { user: x.user, pass: x.pass }; } }); }
116 amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.DnsSuffix = result; } if ((flags & 4) == 0) { if (func != null) { func(amtMeiTmpState); } } });
117 if ((flags & 4) != 0) {
118 amtMei.getHashHandles(function (handles) {
119 if ((handles != null) && (handles.length > 0)) { amtMeiTmpState.Hashes = []; } else { func(amtMeiTmpState); }
120 var exitOnCount = handles.length;
121 for (var i = 0; i < handles.length; ++i) { this.getCertHashEntry(handles[i], function (hashresult) { amtMeiTmpState.Hashes.push(hashresult); if (--exitOnCount == 0) { if (func != null) { func(amtMeiTmpState); } } }); }
124 } catch (e) { if (func != null) { func(null); } return; }
127 // Called on MicroLMS Intel AMT user notification
128 var handleAmtNotification = function (notifyMsg) {
129 if ((notifyMsg == null) || (notifyMsg.Body == null) || (notifyMsg.Body.MessageID == null) || (notifyMsg.Body.MessageArguments == null)) return null;
130 var amtMessage = notifyMsg.Body.MessageID, amtMessageArg = notifyMsg.Body.MessageArguments[0], notify = null;
132 switch (amtMessage) {
133 case 'iAMT0050': { if (amtMessageArg == '48') { notify = "Intel® AMT Serial-over-LAN connected"; } else if (amtMessageArg == '49') { notify = "Intel® AMT Serial-over-LAN disconnected"; } break; } // SOL
134 case 'iAMT0052': { if (amtMessageArg == '1') { notify = "Intel® AMT KVM connected"; } else if (amtMessageArg == '2') { notify = "Intel® AMT KVM disconnected"; } break; } // KVM
138 // Sent to the entire group, no sessionid or userid specified.
139 if (notify != null) { agent.SendCommand({ 'action': 'msg', 'type': 'notify', 'value': notify, 'tag': 'general', 'amtMessage': amtMessage }); }
143 obj.lmsreset = function () {
144 //debug('Binding to LMS');
147 var lme_heci = require('amt-lme');
148 obj.lmsstate = amtLmsState = 1;
149 amtLms = new lme_heci();
150 amtLms.on('error', function (e) { amtLmsState = 0; obj.lmsstate = 0; amtLms = null; debug("LMS error: " + e); });
151 amtLms.on('connect', function () { amtLmsState = 2; obj.lmsstate = 2; debug("LMS connected"); });
152 amtLms.on('bind', function (map) { obj._mapping = map; obj.emit('portBinding_LMS', map); });
153 amtLms.on('notify', function (data, options, code) { handleAmtNotification(data); });
155 require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "ex: " + ex });
156 amtLmsState = -1; obj.lmsstate = -1; amtLms = null;
160 // Start host based ACM activation with TLS
161 obj.startConfigurationHBased = function startConfigurationHBased(certHash, hostVpn, dnsSuffixList, func) {
162 if ((amtMei == null) || (amtMeiState < 2)) { if (func != null) { func({ status: -100 }); } return; }
163 amtMei.startConfigurationHBased(certHash, hostVpn, dnsSuffixList, func);
168module.exports = AmtManager;