amt-manage.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. Copyright 2018-2021 Intel Corporation
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /**
  14. * @fileoverview Intel(r) AMT Management
  15. * @author Ylian Saint-Hilaire
  16. * @version v0.1.0
  17. */
  18. /**
  19. * Construct a AmtStackCreateService object, this ia the main Intel AMT communication stack.
  20. * @constructor
  21. */
  22. function AmtManager(agent, db, isdebug) {
  23. var sendConsole = function (msg) { agent.SendCommand({ 'action': 'msg', 'type': 'console', 'value': msg }); }
  24. var debug = function (msg) { if (isdebug) { sendConsole('amt-manager: ' + msg + '<br />'); } }
  25. var amtMei = null, amtMeiState = 0;
  26. var amtLms = null, amtLmsState = 0;
  27. var amtGetVersionResult = null;
  28. var obj = this;
  29. var mestate;
  30. var trustedHashes = null;;
  31. require('events').EventEmitter.call(obj, true)
  32. .createEvent('stateChange_LMS')
  33. .createEvent('portBinding_LMS');
  34. obj._lmsstate = 0;
  35. obj._mapping = [];
  36. obj.on('newListener', function (name, callback) {
  37. if (name == 'portBinding_LMS') { callback.call(this, this._mapping); }
  38. });
  39. Object.defineProperty(obj, 'lmsstate',
  40. {
  41. get: function () { return (this._lmsstate); },
  42. set: function (value) { if (this._lmsstate != value) { this._lmsstate = value; this.emit('stateChange_LMS', value); } }
  43. });
  44. obj.state = 0;
  45. obj.onStateChange = null;
  46. obj.setDebug = function (x) { isdebug = x; }
  47. // Try to load up the MEI module
  48. var rebindToMeiRetrys = 0;
  49. obj.reset = function () {
  50. ++rebindToMeiRetrys;
  51. obj.amtMei = null, amtMei = null, amtMeiState = 0, amtLms = null, amtLmsState = 0, obj.state = 0, obj.lmsstate = 0;
  52. //debug('Binding to MEI');
  53. try {
  54. var amtMeiLib = require('amt-mei');
  55. obj.amtMei = amtMei = new amtMeiLib();
  56. amtMei.on('error', function (e) { debug('MEI error'); amtMei = null; amtMeiState = -1; obj.state = -1; if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); } });
  57. amtMei.getVersion(function (result) {
  58. if (result == null) {
  59. obj.state = amtMeiState = -1;
  60. if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
  61. if (rebindToMeiRetrys < 10) { setTimeout(obj.reset, 10000); }
  62. } else {
  63. amtGetVersionResult = result;
  64. obj.state = amtMeiState = 2;
  65. rebindToMeiRetrys = 0;
  66. if (obj.onStateChange != null) { obj.onStateChange(amtMeiState); }
  67. //debug('MEI binded');
  68. obj.lmsreset();
  69. }
  70. });
  71. } catch (ex) { debug("MEI exception: " + ex); amtMei = null; amtMeiState = -1; obj.state = -1; }
  72. }
  73. // Get Intel MEI State in a flexible way
  74. // Flags: 1 = Versions, 2 = OsAdmin, 4 = Hashes, 8 = Network
  75. var getMeiStateCache = {}; // Some MEI calls will only be made once and cached here.
  76. obj.getMeiState = function(flags, func) {
  77. if ((amtMei == null) || (amtMeiState < 2)) { if (func != null) { func(null); } return; }
  78. try {
  79. var amtMeiTmpState = { 'core-ver': 1, OsHostname: require('os').hostname(), Flags: 0 }; // Flags: 1=EHBC, 2=CCM, 4=ACM
  80. if (getMeiStateCache.MeiVersion != null) { amtMeiTmpState.MeiVersion = getMeiStateCache.MeiVersion; } else { amtMei.getProtocolVersion(function (result) { if (result != null) { getMeiStateCache.MeiVersion = amtMeiTmpState.MeiVersion = result; } }); }
  81. if ((flags & 1) != 0) {
  82. if (getMeiStateCache.Versions != null) {
  83. amtMeiTmpState.Versions = getMeiStateCache.Versions;
  84. } else {
  85. 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; } } });
  86. }
  87. }
  88. amtMei.getProvisioningMode(function (result) { if (result) { amtMeiTmpState.ProvisioningMode = result.mode; } });
  89. 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.
  90. amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } });
  91. 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
  92. //amtMei.getMACAddresses(function (result) { if (result) { amtMeiTmpState.mac = result; } });
  93. if ((flags & 8) != 0) {
  94. amtMei.getLanInterfaceSettings(0, function (result) {
  95. if (result) {
  96. amtMeiTmpState.net0 = result;
  97. var fqdn = null, interfaces = require('os').networkInterfaces(); // Look for the DNS suffix for the Intel AMT Ethernet interface
  98. 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; } } }
  99. }
  100. });
  101. amtMei.getLanInterfaceSettings(1, function (result) { if (result) { amtMeiTmpState.net1 = result; } });
  102. }
  103. 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; } }); }
  104. if ((flags & 2) != 0) { amtMei.getLocalSystemAccount(function (x) { if ((x != null) && x.user && x.pass) { amtMeiTmpState.OsAdmin = { user: x.user, pass: x.pass }; } }); }
  105. amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.DnsSuffix = result; } if ((flags & 4) == 0) { if (func != null) { func(amtMeiTmpState); } } });
  106. if ((flags & 4) != 0) {
  107. amtMei.getHashHandles(function (handles) {
  108. if ((handles != null) && (handles.length > 0)) { amtMeiTmpState.Hashes = []; } else { func(amtMeiTmpState); }
  109. var exitOnCount = handles.length;
  110. 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); } } }); }
  111. });
  112. }
  113. } catch (e) { if (func != null) { func(null); } return; }
  114. }
  115. // Called on MicroLMS Intel AMT user notification
  116. var handleAmtNotification = function (notifyMsg) {
  117. if ((notifyMsg == null) || (notifyMsg.Body == null) || (notifyMsg.Body.MessageID == null) || (notifyMsg.Body.MessageArguments == null)) return null;
  118. var amtMessage = notifyMsg.Body.MessageID, amtMessageArg = notifyMsg.Body.MessageArguments[0], notify = null;
  119. switch (amtMessage) {
  120. case 'iAMT0050': { if (amtMessageArg == '48') { notify = "Intel&reg; AMT Serial-over-LAN connected"; } else if (amtMessageArg == '49') { notify = "Intel&reg; AMT Serial-over-LAN disconnected"; } break; } // SOL
  121. case 'iAMT0052': { if (amtMessageArg == '1') { notify = "Intel&reg; AMT KVM connected"; } else if (amtMessageArg == '2') { notify = "Intel&reg; AMT KVM disconnected"; } break; } // KVM
  122. default: { break; }
  123. }
  124. // Sent to the entire group, no sessionid or userid specified.
  125. if (notify != null) { agent.SendCommand({ 'action': 'msg', 'type': 'notify', 'value': notify, 'tag': 'general', 'amtMessage': amtMessage }); }
  126. }
  127. // Launch LMS
  128. obj.lmsreset = function () {
  129. //debug('Binding to LMS');
  130. obj.lmsstate = 0;
  131. try {
  132. var lme_heci = require('amt-lme');
  133. obj.lmsstate = amtLmsState = 1;
  134. amtLms = new lme_heci();
  135. amtLms.on('error', function (e) { amtLmsState = 0; obj.lmsstate = 0; amtLms = null; debug("LMS error: " + e); });
  136. amtLms.on('connect', function () { amtLmsState = 2; obj.lmsstate = 2; debug("LMS connected"); });
  137. amtLms.on('bind', function (map) { obj._mapping = map; obj.emit('portBinding_LMS', map); });
  138. amtLms.on('notify', function (data, options, code) { handleAmtNotification(data); });
  139. } catch (ex) {
  140. require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "ex: " + ex });
  141. amtLmsState = -1; obj.lmsstate = -1; amtLms = null;
  142. }
  143. }
  144. // Start host based ACM activation with TLS
  145. obj.startConfigurationHBased = function startConfigurationHBased(certHash, hostVpn, dnsSuffixList, func) {
  146. if ((amtMei == null) || (amtMeiState < 2)) { if (func != null) { func({ status: -100 }); } return; }
  147. amtMei.startConfigurationHBased(certHash, hostVpn, dnsSuffixList, func);
  148. }
  149. }
  150. module.exports = AmtManager;