More Intel AMT ACM activation work.
This commit is contained in:
parent
1d96f89f9d
commit
e45a919c6e
|
@ -484,7 +484,7 @@ function AmtManager(agent, db, isdebug) {
|
|||
// Fetch Intel AMT realm and activation nonce and get ready to ACM activation...
|
||||
if (osamtstack != null) {
|
||||
//debug('Trying to get Intel AMT activation information (1)...');
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch });
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch, uuid: mestate.UUID });
|
||||
} else {
|
||||
//debug('ACM Activation: Trying to get local account info...');
|
||||
amtMei.getLocalSystemAccount(function (x) {
|
||||
|
@ -496,7 +496,7 @@ function AmtManager(agent, db, isdebug) {
|
|||
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 (2)...');
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch });
|
||||
osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToACM2, { fqdn: trustedFqdn, hash: hashMatch, uuid: mestate.UUID });
|
||||
} else {
|
||||
//debug('Unable to get $$OsAdmin password.');
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ function AmtManager(agent, db, isdebug) {
|
|||
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": tag.fqdn, "hash": tag.hash });
|
||||
agent.SendCommand({ "action": "acmactivate", "nonce": fwNonce, "realm": digestRealm, "fqdn": tag.fqdn, "hash": tag.hash, "uuid": tag.uuid });
|
||||
}
|
||||
|
||||
// Called when the server responds with a ACM activation signature.
|
||||
|
|
|
@ -29,12 +29,13 @@ module.exports.CertificateOperations = function (parent) {
|
|||
const TopLevelDomainExtendedSupport = { 'net': 2, 'com': 2, 'arpa': 3, 'org': 2, 'gov': 2, 'edu': 2, 'de': 2, 'fr': 3, 'cn': 3, 'nl': 3, 'br': 3, 'mx': 3, 'uk': 3, 'pl': 3, 'tw': 3, 'ca': 3, 'fi': 3, 'be': 3, 'ru': 3, 'se': 3, 'ch': 2, 'dk': 2, 'ar': 3, 'es': 3, 'no': 3, 'at': 3, 'in': 3, 'tr': 3, 'cz': 2, 'ro': 3, 'hu': 3, 'nz': 3, 'pt': 3, 'il': 3, 'gr': 3, 'co': 3, 'ie': 3, 'za': 3, 'th': 3, 'sg': 3, 'hk': 3, 'cl': 2, 'lt': 3, 'id': 3, 'hr': 3, 'ee': 3, 'bg': 3, 'ua': 2 };
|
||||
|
||||
// Sign a Intel AMT ACM activation request
|
||||
obj.signAcmRequest = function (domain, request, user, pass) {
|
||||
obj.signAcmRequest = function (domain, request, user, pass, ipport, nodeid, meshid, computerName, agentId) {
|
||||
if ((domain == null) || (domain.amtacmactivation == null) || (domain.amtacmactivation.certs == null) || (request == null) || (request.nonce == null) || (request.realm == null) || (request.fqdn == null) || (request.hash == null)) return null;
|
||||
if (parent.common.validateString(request.nonce, 16, 256) == false) return null;
|
||||
if (parent.common.validateString(request.realm, 16, 256) == false) return null;
|
||||
if (parent.common.validateString(request.fqdn, 4, 256) == false) return null;
|
||||
if (parent.common.validateString(request.hash, 16, 256) == false) return null;
|
||||
if (parent.common.validateString(request.uuid, 36, 36) == false) return null;
|
||||
|
||||
// Look for the signing certificate
|
||||
var signkey = null, certChain = null, hashAlgo = null, certIndex = null;
|
||||
|
@ -60,10 +61,22 @@ module.exports.CertificateOperations = function (parent) {
|
|||
signature = signer.sign(signkey, 'base64');
|
||||
} catch (ex) { return null; }
|
||||
|
||||
// Log the activation request, logging is a required step for activation.
|
||||
if (obj.logAmtActivation(domain, { time: new Date(), domain: domain.id, amtUuid: request.uuid, certHash: request.hash, hashType: hashAlgo, amtRealm: request.realm, amtFqdn: request.fqdn, user: user, password: pass, ipport: ipport, nodeid: nodeid, meshid: meshid, computerName: computerName, agentId: agentId }) == false) return null;
|
||||
|
||||
// Return the signature with the computed account password hash
|
||||
return { 'action': 'acmactivate', 'signature': signature, 'password': obj.crypto.createHash('md5').update(user + ':' + request.realm + ':' + pass).digest('hex'), 'nonce': mcNonce.toString('base64'), 'certs': certChain };
|
||||
}
|
||||
|
||||
// Log the Intel AMT activation operation
|
||||
obj.logAmtActivation = function (domain, x) {
|
||||
if ((domain.amtacmactivation == null) || (domain.amtacmactivation.log == null) || (typeof domain.amtacmactivation.log != 'string') || (x == null)) return true;
|
||||
var logpath = null;
|
||||
if ((domain.amtacmactivation.log.length >= 2) && ((domain.amtacmactivation.log[0] == '/') || (domain.amtacmactivation.log[1] == ':'))) { logpath = domain.amtacmactivation.log; } else { logpath = parent.path.join(obj.parent.datapath, domain.amtacmactivation.log); }
|
||||
try { obj.fs.appendFileSync(logpath, JSON.stringify(x) + '\r\n'); } catch (ex) { console.log(ex); return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
// Load Intel AMT ACM activation certificates
|
||||
obj.loadIntelAmtAcmCerts = function (amtacmactivation) {
|
||||
if (amtacmactivation == null) return;
|
||||
|
|
31
meshagent.js
31
meshagent.js
|
@ -1210,10 +1210,30 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||
}
|
||||
case 'acmactivate':
|
||||
{
|
||||
if (obj.agentInfo.capabilities & 0x20) return; // If this is a temporary device, don't do ACM activation.
|
||||
|
||||
// Get the current Intel AMT policy
|
||||
var mesh = parent.meshes[obj.dbMeshKey];
|
||||
if ((mesh == null) || (mesh.amt == null) || (mesh.amt.type != 3) || (domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (mesh.amt.password == null)) break; // If this is not the right policy, ignore this.
|
||||
|
||||
// Get the Intel AMT admin password, randomize if needed.
|
||||
var amtpassword = ((mesh.amt.password == '') ? getRandomAmtPassword() : mesh.amt.password);
|
||||
if (checkAmtPassword(amtpassword) == false) return; // Invalid Intel AMT password, this should never happen.
|
||||
|
||||
// Agent is asking the server to sign an Intel AMT ACM activation request
|
||||
//console.log(command);
|
||||
var signResponse = parent.parent.certificateOperations.signAcmRequest(domain, command, 'admin', 'P@ssw0rd'); // TODO: Place account credentials!!!
|
||||
if (signResponse != null) { obj.send(JSON.stringify(signResponse)); }
|
||||
var signResponse = parent.parent.certificateOperations.signAcmRequest(domain, command, 'admin', amtpassword, obj.remoteaddrport, obj.dbNodeKey, obj.dbMeshKey, obj.agentInfo.computerName, obj.agentInfo.agentId); // TODO: Place account credentials!!!
|
||||
if (signResponse != null) {
|
||||
// Log this activation event
|
||||
var event = { etype: 'node', action: 'amtactivate', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Device requested Intel AMT ACM activation, FQDN: ' + command.fqdn, ip: obj.remoteaddrport };
|
||||
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
|
||||
parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, event);
|
||||
|
||||
// Update the device Intel AMT information
|
||||
ChangeAgentCoreInfo({ "intelamt": { user: 'admin', pass: amtpassword, uuid: command.uuid, realm: command.realm } });
|
||||
|
||||
// Send the activation response
|
||||
//obj.send(JSON.stringify(signResponse));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'diagnostic':
|
||||
|
@ -1307,6 +1327,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||
if (device.intelamt.flags) { changes.push('AMT flags (' + device.intelamt.flags + ' --> ' + command.intelamt.flags + ')'); } else { changes.push('AMT flags (' + command.intelamt.flags + ')'); }
|
||||
device.intelamt.flags = command.intelamt.flags; change = 1; log = 1;
|
||||
}
|
||||
if ((command.intelamt.realm != null) && (device.intelamt.realm != command.intelamt.realm)) { changes.push('AMT realm'); device.intelamt.realm = command.intelamt.realm; change = 1; log = 1; }
|
||||
if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { changes.push('AMT host'); device.intelamt.host = command.intelamt.host; change = 1; log = 1; }
|
||||
if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { changes.push('AMT uuid'); device.intelamt.uuid = command.intelamt.uuid; change = 1; log = 1; }
|
||||
if ((command.intelamt.user != null) && (device.intelamt.user != command.intelamt.user)) { changes.push('AMT user'); device.intelamt.user = command.intelamt.user; change = 1; log = 1; }
|
||||
|
@ -1420,5 +1441,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||
});
|
||||
}
|
||||
|
||||
// Generate a random Intel AMT password
|
||||
function checkAmtPassword(p) { return (p.length > 7) && (/\d/.test(p)) && (/[a-z]/.test(p)) && (/[A-Z]/.test(p)) && (/\W/.test(p)); }
|
||||
function getRandomAmtPassword() { var p; do { p = Buffer.from(parent.crypto.randomBytes(9), 'binary').toString('base64').split('/').join('@'); } while (checkAmtPassword(p) == false); return p; }
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
|
|
@ -734,12 +734,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
r = parent.db.getBackupConfig();
|
||||
break;
|
||||
}
|
||||
case 'acm': {
|
||||
var acmrequest = { action: 'acmactivate', nonce: 'H9e099o2wIhnRkjd5vXJWBceqIY=', realm: 'Digest:4DCA0000000000000000000000000000', fqdn: 'vprodemo.com', hash: 'c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4' };
|
||||
var response = parent.parent.certificateOperations.signAcmRequest(domain, acmrequest, 'admin', 'P@ssw0rd');
|
||||
r = 'ACM Response: ' + JSON.stringify(response);
|
||||
break;
|
||||
}
|
||||
default: { // This is an unknown command, return an error message
|
||||
r = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue