mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-03-09 15:40:18 +00:00
More work on ACM activation, MiniRouter self-signed.
This commit is contained in:
parent
ae83965976
commit
a4a3a5a5cd
53 changed files with 692 additions and 4670 deletions
|
@ -169,23 +169,23 @@ function lme_heci(options) {
|
|||
}
|
||||
}
|
||||
if (this[name][port] == null)
|
||||
{ // Bind a new server socket if not already present
|
||||
this[name][port] = require('net').createServer();
|
||||
this[name][port].HECI = this;
|
||||
|
||||
{
|
||||
try {
|
||||
// Bind a new server socket if not already present
|
||||
this[name][port] = require('net').createServer();
|
||||
this[name][port].HECI = this;
|
||||
if (lme_port_offset == 0) {
|
||||
this[name][port].listen({ port: port, host: '127.0.0.1' }); // Normal mode
|
||||
} else {
|
||||
this[name][port].listen({ port: (port + lme_port_offset) }); // Debug mode
|
||||
}
|
||||
} catch (ex) { console.log('Binding error, LMS port ' + (port + lme_port_offset) + ': ' + ex) } // TODO: We can't bind
|
||||
this[name][port].on('connection', function (socket) {
|
||||
//console.log('New [' + socket.remoteFamily + '] TCP Connection on: ' + socket.remoteAddress + ' :' + socket.localPort);
|
||||
this.HECI.LMS.bindDuplexStream(socket, socket.remoteFamily, socket.localPort - lme_port_offset);
|
||||
});
|
||||
this._binded[port] = true;
|
||||
this.LMS.emit('bind', this._binded);
|
||||
this[name][port].on('connection', function (socket) {
|
||||
//console.log('New [' + socket.remoteFamily + '] TCP Connection on: ' + socket.remoteAddress + ' :' + socket.localPort);
|
||||
this.HECI.LMS.bindDuplexStream(socket, socket.remoteFamily, socket.localPort - lme_port_offset);
|
||||
});
|
||||
this._binded[port] = true;
|
||||
this.LMS.emit('bind', this._binded);
|
||||
} catch (ex) { console.log(ex, 'Port ' + port); }
|
||||
}
|
||||
var outBuffer = Buffer.alloc(5);
|
||||
outBuffer.writeUInt8(81, 0);
|
||||
|
|
|
@ -35,6 +35,7 @@ function AmtManager(agent, db, isdebug) {
|
|||
var amtpolicy = null;
|
||||
var obj = this;
|
||||
var mestate;
|
||||
var trustedHashes = null;;
|
||||
obj.state = 0;
|
||||
obj.lmsstate = 0;
|
||||
obj.onStateChange = null;
|
||||
|
@ -432,13 +433,31 @@ function AmtManager(agent, db, isdebug) {
|
|||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Get Intel AMT activation hashes
|
||||
//
|
||||
obj.getTrustedHashes = function (func, tag) {
|
||||
if (trustedHashes != null) { func(tag); }
|
||||
trustedHashes = [];
|
||||
amtMei.getHashHandles(function (handles) {
|
||||
var exitOnCount = handles.length;
|
||||
for (var i = 0; i < handles.length; ++i) {
|
||||
this.getCertHashEntry(handles[i], function (result) {
|
||||
if (result.isActive == 1) { trustedHashes.push(result.certificateHash.toLowerCase()); }
|
||||
if (--exitOnCount == 0) { func(tag); }
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Activate Intel AMT to ACM
|
||||
//
|
||||
|
||||
obj.activeToACM = function (mestate) {
|
||||
//debug('TrustedHashes: ' + JSON.stringify(trustedHashes));
|
||||
//debug('ProvisioningState: ' + JSON.stringify(mestate.ProvisioningState));
|
||||
if (mestate.ProvisioningState != 0) return; // Can't activate unless in "PRE" activation mode.
|
||||
if ((mestate.ProvisioningState != 0) || (amtpolicy == null) || (amtpolicy.match == null)) return; // Can't activate unless in "PRE" activation mode & policy is present.
|
||||
var trustedFqdn = null;
|
||||
//debug('Wired Interface: ' + JSON.stringify(mestate.net0));
|
||||
if ((mestate.net0 == null) && (mestate.net0.enabled != 0)) return; // Can't activate unless wired interface is active
|
||||
|
@ -448,19 +467,26 @@ function AmtManager(agent, db, isdebug) {
|
|||
var interfaces = require('os').networkInterfaces();
|
||||
for (var i in interfaces) {
|
||||
for (var j in interfaces[i]) {
|
||||
if ((interfaces[i][j].mac == mestate.net0.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { trustedFqdn = interfaces[i][j].fqdn; }
|
||||
if ((interfaces[i][j].mac == mestate.net0.mac) && (interfaces[i][j].fqdn != null) && (interfaces[i][j].fqdn != '')) { trustedFqdn = interfaces[i][j].fqdn.toLowerCase(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trustedFqdn == null) return; // No trusted DNS suffix.
|
||||
//debug('TrustedFqdn: ' + trustedFqdn);
|
||||
|
||||
|
||||
// Check if we have a ACM policy match
|
||||
var hashMatch = false;
|
||||
for (var i in amtpolicy.match) { var m = amtpolicy.match[i]; if (m.cn == trustedFqdn) { for (var j in trustedHashes) { if ((trustedHashes[j] == m.sha256) || (trustedHashes[j] == m.sha1)) { hashMatch = trustedHashes[j]; } } } }
|
||||
if (hashMatch == null) return; // No certificate / FQDN match
|
||||
debug('Policy: ' + JSON.stringify(amtpolicy));
|
||||
debug('HashMatch: ' + hashMatch);
|
||||
|
||||
// Fetch Intel AMT realm and activation nonce and get ready to ACM activation...
|
||||
if (osamtstack != null) {
|
||||
//debug('Trying to get Intel AMT activation information...');
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, trustedFqdn);
|
||||
debug('Trying to get Intel AMT activation information (1)...');
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch });
|
||||
} else {
|
||||
//debug('ACM Activation: Trying to get local account info...');
|
||||
debug('ACM Activation: Trying to get local account info...');
|
||||
amtMei.getLocalSystemAccount(function (x) {
|
||||
if ((x != null) && x.user && x.pass) {
|
||||
//debug('Intel AMT local account info: User=' + x.user + ', Pass=' + x.pass + '.');
|
||||
|
@ -469,21 +495,48 @@ function AmtManager(agent, db, isdebug) {
|
|||
var amt = require('amt');
|
||||
oswsstack = new wsman(transport, '127.0.0.1', 16992, x.user, x.pass, false);
|
||||
osamtstack = new amt(oswsstack);
|
||||
//debug('Trying to get Intel AMT activation information...');
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, trustedFqdn);
|
||||
debug('Trying to get Intel AMT activation information (2)...');
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch });
|
||||
} else {
|
||||
//debug('Unable to get $$OsAdmin password.');
|
||||
debug('Unable to get $$OsAdmin password.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function activeToACM2(stack, name, responses, status, trustedFqdn) {
|
||||
debug('activeToACM2: ' + trustedFqdn);
|
||||
function activeToACM2(stack, name, responses, status, tag) {
|
||||
debug('activeToACM2 status=' + status);
|
||||
if (status != 200) return;
|
||||
var fwNonce = responses['IPS_HostBasedSetupService'].response['ConfigurationNonce'];
|
||||
var digestRealm = responses['AMT_GeneralSettings'].response['DigestRealm'];
|
||||
agent.SendCommand({ "action": "acmactivate", "nonce": fwNonce, "realm": digestRealm, "fqdn": trustedFqdn });
|
||||
agent.SendCommand({ "action": "acmactivate", "nonce": fwNonce, "realm": digestRealm, "fqdn": tag.fqdn, "hash": tag.hash });
|
||||
}
|
||||
|
||||
// Called when the server responds with a ACM activation signature.
|
||||
obj.setAcmResponse = function (acmdata) {
|
||||
debug('setAcmResponse=' + JSON.stringify(acmdata));
|
||||
acmdata.index = 0;
|
||||
//performAcmActivation(acmdata);
|
||||
}
|
||||
|
||||
// Recursive function to inject the provisioning certificates into AMT in the proper order and completes ACM activation
|
||||
function performAcmActivation(acmdata) {
|
||||
var leaf = (acmdata.index == 0), root = (acmdata.index == (acmdata.certChain.length - 1));
|
||||
if (acmdata.index < acmdata.certChain.length) {
|
||||
if (acmdata.certChain[acmdata.index] != null) {
|
||||
debug('Calling AddNextCertInChain(' + acmdata.index + ')');
|
||||
osamtstack.IPS_HostBasedSetupService_AddNextCertInChain(acmdata.certChain[acmdata.index], leaf, root, function (stack, name, responses, status) {
|
||||
if (status !== 200) { debug('AddNextCertInChain status=' + status); return; }
|
||||
else if (responses['Body']['ReturnValue'] !== 0) { debug('AddNextCertInChain error=' + responses['Body']['ReturnValue']); return; }
|
||||
else { acmdata.index++; performAcmActivation(acmdata); }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
debug('Calling AdminSetup()');
|
||||
osamtstack.IPS_HostBasedSetupService_AdminSetup(2, acmdata.password, acmdata.nonce, 2, acmdata.signature,
|
||||
function (stack, name, responses, status) { debug('DONE: ' + status); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -556,13 +609,11 @@ function AmtManager(agent, db, isdebug) {
|
|||
obj.getAmtInfo(function (meinfo) {
|
||||
if ((amtpolicy.type == 1) && (meinfo.ProvisioningState == 2) && ((meinfo.Flags & 2) != 0)) {
|
||||
// CCM Deactivation Policy.
|
||||
wsstack = null;
|
||||
amtstack = null;
|
||||
wsstack = amtstack = null;
|
||||
obj.deactivateCCM();
|
||||
} else if ((amtpolicy.type == 2) && (meinfo.ProvisioningState == 0)) {
|
||||
// CCM Activation Policy
|
||||
wsstack = null;
|
||||
amtstack = null;
|
||||
wsstack = amtstack = null;
|
||||
if ((amtpolicy.password == null) || (amtpolicy.password == '')) { intelAmtAdminPass = null; }
|
||||
obj.activeToCCM(intelAmtAdminPass);
|
||||
} else if ((amtpolicy.type == 2) && (meinfo.ProvisioningState == 2) && (intelAmtAdminPass != null) && ((meinfo.Flags & 2) != 0)) {
|
||||
|
@ -577,7 +628,7 @@ function AmtManager(agent, db, isdebug) {
|
|||
try { amtstack.BatchEnum(null, wsmanQuery, wsmanPassTestResponse); } catch (ex) { debug(ex); }
|
||||
} else if ((amtpolicy.type == 3) && (meinfo.ProvisioningState == 0)) {
|
||||
// ACM Activation Policy
|
||||
obj.activeToACM(meinfo);
|
||||
obj.getTrustedHashes(obj.activeToACM, meinfo);
|
||||
} else {
|
||||
// Other possible cases...
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ function amt_heci() {
|
|||
emitterUtils.createEvent('error');
|
||||
|
||||
var heci = require('heci');
|
||||
var sendConsole = function (msg) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg }); }
|
||||
var sendConsole = function (msg) { try { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg }); } catch (ex) { } }
|
||||
|
||||
this._ObjectID = "pthi";
|
||||
this._rq = new Q();
|
||||
|
|
|
@ -121,66 +121,68 @@ function _getChildElementsByTagName(name) { var ret = []; if (this.childNodes !=
|
|||
function _getChildElementsByTagNameNS(ns, name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name && (ns == '*' || this.childNodes[node].namespace == ns)) { ret.push(this.childNodes[node]); } } } return (ret); }
|
||||
function _xmlTraverseAllRec(nodes, func) { for (var i in nodes) { func(nodes[i]); if (nodes[i].childNodes) { _xmlTraverseAllRec(nodes[i].childNodes, func); } } }
|
||||
function _turnToXmlRec(text) {
|
||||
if (text == null) return null;
|
||||
var elementStack = new _treeBuilder(), lastElement = null, x1 = text.split('<'), ret = [], element = null, currentElementName = null;
|
||||
for (var i in x1) {
|
||||
var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0];
|
||||
if ((elementName.length > 0) && (elementName[0] != '?')) {
|
||||
if (elementName[0] != '/') {
|
||||
var attributes = [], localName, localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0];
|
||||
Object.defineProperty(attributes, "get",
|
||||
{
|
||||
value: function () {
|
||||
if (arguments.length == 1) {
|
||||
for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } }
|
||||
}
|
||||
else if (arguments.length == 2) {
|
||||
for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } }
|
||||
}
|
||||
else {
|
||||
throw ('attributes.get(): Invalid number of parameters');
|
||||
}
|
||||
}
|
||||
});
|
||||
elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} });
|
||||
// Parse Attributes
|
||||
if (x3.length > 0) {
|
||||
var skip = false;
|
||||
for (var j in x3) {
|
||||
if (x3[j] == '/') {
|
||||
// This is an empty Element
|
||||
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||
elementStack.peek().textContent = '';
|
||||
lastElement = elementStack.pop();
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
var k = x3[j].indexOf('=');
|
||||
if (k > 0) {
|
||||
var attrName = x3[j].substring(0, k);
|
||||
var attrValue = x3[j].substring(k + 2, x3[j].length - 1);
|
||||
var attrNS = elementStack.getNamespace('*');
|
||||
|
||||
if (attrName == 'xmlns') {
|
||||
elementStack.addNamespace('*', attrValue);
|
||||
attrNS = attrValue;
|
||||
} else if (attrName.startsWith('xmlns:')) {
|
||||
elementStack.addNamespace(attrName.substring(6), attrValue);
|
||||
} else {
|
||||
var ax = attrName.split(':');
|
||||
if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); }
|
||||
try {
|
||||
if (text == null) return null;
|
||||
var elementStack = new _treeBuilder(), lastElement = null, x1 = text.split('<'), ret = [], element = null, currentElementName = null;
|
||||
for (var i in x1) {
|
||||
var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0];
|
||||
if ((elementName.length > 0) && (elementName[0] != '?')) {
|
||||
if (elementName[0] != '/') {
|
||||
var attributes = [], localName, localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0];
|
||||
Object.defineProperty(attributes, "get",
|
||||
{
|
||||
value: function () {
|
||||
if (arguments.length == 1) {
|
||||
for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } }
|
||||
}
|
||||
else if (arguments.length == 2) {
|
||||
for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } }
|
||||
}
|
||||
else {
|
||||
throw ('attributes.get(): Invalid number of parameters');
|
||||
}
|
||||
var x = { name: attrName, value: attrValue }
|
||||
if (attrNS != null) x.namespace = attrNS;
|
||||
elementStack.peek().attributes.push(x);
|
||||
}
|
||||
});
|
||||
elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} });
|
||||
// Parse Attributes
|
||||
if (x3.length > 0) {
|
||||
var skip = false;
|
||||
for (var j in x3) {
|
||||
if (x3[j] == '/') {
|
||||
// This is an empty Element
|
||||
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||
elementStack.peek().textContent = '';
|
||||
lastElement = elementStack.pop();
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
var k = x3[j].indexOf('=');
|
||||
if (k > 0) {
|
||||
var attrName = x3[j].substring(0, k);
|
||||
var attrValue = x3[j].substring(k + 2, x3[j].length - 1);
|
||||
var attrNS = elementStack.getNamespace('*');
|
||||
|
||||
if (attrName == 'xmlns') {
|
||||
elementStack.addNamespace('*', attrValue);
|
||||
attrNS = attrValue;
|
||||
} else if (attrName.startsWith('xmlns:')) {
|
||||
elementStack.addNamespace(attrName.substring(6), attrValue);
|
||||
} else {
|
||||
var ax = attrName.split(':');
|
||||
if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); }
|
||||
}
|
||||
var x = { name: attrName, value: attrValue }
|
||||
if (attrNS != null) x.namespace = attrNS;
|
||||
elementStack.peek().attributes.push(x);
|
||||
}
|
||||
}
|
||||
if (skip) { continue; }
|
||||
}
|
||||
if (skip) { continue; }
|
||||
}
|
||||
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||
if (x2[1]) { elementStack.peek().textContent = x2[1]; }
|
||||
} else { lastElement = elementStack.pop(); }
|
||||
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
|
||||
if (x2[1]) { elementStack.peek().textContent = x2[1]; }
|
||||
} else { lastElement = elementStack.pop(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ex) { return null; }
|
||||
return lastElement;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue