mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Improved Intel AMT activation logging.
This commit is contained in:
parent
2df78feb6b
commit
5a3e68a935
@ -1093,7 +1093,7 @@ function createMeshCore(agent) {
|
|||||||
};
|
};
|
||||||
apftunnel = require('apfclient')({ debug: false }, apfarg);
|
apftunnel = require('apfclient')({ debug: false }, apfarg);
|
||||||
apftunnel.onJsonControl = function (data) {
|
apftunnel.onJsonControl = function (data) {
|
||||||
//if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); } // Display a console message (DEBUG)
|
if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); } // Display a console message (DEBUG)
|
||||||
if (data.action == 'mestate') { getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
|
if (data.action == 'mestate') { getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
|
||||||
if (data.action == 'deactivate') { // Request CCM deactivation
|
if (data.action == 'deactivate') { // Request CCM deactivation
|
||||||
var amtMeiModule, amtMei;
|
var amtMeiModule, amtMei;
|
||||||
|
@ -1452,6 +1452,13 @@ module.exports.CreateAmtManager = function (parent) {
|
|||||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||||
if (status != 200) { dev.consoleMsg("Failed to get Intel AMT state."); removeAmtDevice(dev); return; }
|
if (status != 200) { dev.consoleMsg("Failed to get Intel AMT state."); removeAmtDevice(dev); return; }
|
||||||
if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { dev.consoleMsg("Client control mode activation not allowed."); removeAmtDevice(dev); return; }
|
if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { dev.consoleMsg("Client control mode activation not allowed."); removeAmtDevice(dev); return; }
|
||||||
|
|
||||||
|
// Log the activation request, logging is a required step for activation.
|
||||||
|
if (parent.certificateOperations.logAmtActivation(domain, { time: new Date(), action: 'ccmactivate', domain: dev.domainid, amtUuid: dev.mpsConnection.tag.meiState.UUID, amtRealm: responses['AMT_GeneralSettings'].response['DigestRealm'], user: 'admin', password: dev.temp.pass, ipport: dev.mpsConnection.remoteAddr + ':' + dev.mpsConnection.remotePort, nodeid: dev.nodeid, meshid: dev.meshid, computerName: dev.name }) == false) {
|
||||||
|
dev.consoleMsg("Unable to log operation."); removeAmtDevice(dev); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform CCM activation
|
||||||
dev.amtstack.IPS_HostBasedSetupService_Setup(2, hex_md5('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + dev.temp.pass).substring(0, 32), null, null, null, null, activateIntelAmtCcmEx2);
|
dev.amtstack.IPS_HostBasedSetupService_Setup(2, hex_md5('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + dev.temp.pass).substring(0, 32), null, null, null, null, activateIntelAmtCcmEx2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1539,8 +1546,9 @@ module.exports.CreateAmtManager = function (parent) {
|
|||||||
|
|
||||||
// Sign the Intel AMT ACM activation request
|
// Sign the Intel AMT ACM activation request
|
||||||
var info = { nonce: responses['IPS_HostBasedSetupService'].response['ConfigurationNonce'], realm: responses['AMT_GeneralSettings'].response['DigestRealm'], fqdn: dev.temp.acminfo.fqdn, hash: dev.temp.acminfo.hash, uuid: dev.mpsConnection.tag.meiState.UUID };
|
var info = { nonce: responses['IPS_HostBasedSetupService'].response['ConfigurationNonce'], realm: responses['AMT_GeneralSettings'].response['DigestRealm'], fqdn: dev.temp.acminfo.fqdn, hash: dev.temp.acminfo.hash, uuid: dev.mpsConnection.tag.meiState.UUID };
|
||||||
var acmdata = parent.certificateOperations.signAcmRequest(parent.config.domains[dev.domainid], info, 'admin', dev.temp.pass, obj.remoteaddrport, dev.nodeid, dev.meshid, dev.name, 0);
|
var acmdata = parent.certificateOperations.signAcmRequest(parent.config.domains[dev.domainid], info, 'admin', dev.temp.pass, dev.mpsConnection.remoteAddr + ':' + dev.mpsConnection.remotePort, dev.nodeid, dev.meshid, dev.name, 0);
|
||||||
if ((acmdata == null) || (acmdata.error != null)) { dev.consoleMsg("Failed to sign ACM nonce."); removeAmtDevice(dev); return; }
|
if (acmdata == null) { dev.consoleMsg("Failed to sign ACM nonce."); removeAmtDevice(dev); return; }
|
||||||
|
if (acmdata.error != null) { dev.consoleMsg(acmdata.errorText); removeAmtDevice(dev); return; }
|
||||||
|
|
||||||
// Log this activation event
|
// Log this activation event
|
||||||
var event = { etype: 'node', action: 'amtactivate', nodeid: dev.nodeid, domain: dev.domainid, msgid: 58, msgArgs: [ dev.temp.acminfo.fqdn ], msg: 'Device requested Intel(R) AMT ACM activation, FQDN: ' + dev.temp.acminfo.fqdn };
|
var event = { etype: 'node', action: 'amtactivate', nodeid: dev.nodeid, domain: dev.domainid, msgid: 58, msgArgs: [ dev.temp.acminfo.fqdn ], msg: 'Device requested Intel(R) AMT ACM activation, FQDN: ' + dev.temp.acminfo.fqdn };
|
||||||
|
@ -31,11 +31,11 @@ module.exports.CertificateOperations = function (parent) {
|
|||||||
// Sign a Intel AMT ACM activation request
|
// Sign a Intel AMT ACM activation request
|
||||||
obj.signAcmRequest = function (domain, request, user, pass, ipport, nodeid, meshid, computerName, agentId) {
|
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 { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid arguments' };
|
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 { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid arguments' };
|
||||||
if (parent.common.validateString(request.nonce, 16, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid nonce argument' };
|
if (parent.common.validateString(request.nonce, 16, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': "Invalid nonce argument." };
|
||||||
if (parent.common.validateString(request.realm, 16, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid realm argument' };
|
if (parent.common.validateString(request.realm, 16, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': "Invalid realm argument." };
|
||||||
if (parent.common.validateString(request.fqdn, 4, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid FQDN argument' };
|
if (parent.common.validateString(request.fqdn, 4, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': "Invalid FQDN argument." };
|
||||||
if (parent.common.validateString(request.hash, 16, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid hash argument' };
|
if (parent.common.validateString(request.hash, 16, 256) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': "Invalid hash argument." };
|
||||||
if (parent.common.validateString(request.uuid, 36, 36) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': 'Invalid UUID argument' };
|
if (parent.common.validateString(request.uuid, 36, 36) == false) return { 'action': 'acmactivate', 'error': 1, 'errorText': "Invalid UUID argument." };
|
||||||
|
|
||||||
// Look for the signing certificate
|
// Look for the signing certificate
|
||||||
var signkey = null, certChain = null, hashAlgo = null, certIndex = null;
|
var signkey = null, certChain = null, hashAlgo = null, certIndex = null;
|
||||||
@ -44,10 +44,10 @@ module.exports.CertificateOperations = function (parent) {
|
|||||||
if ((certEntry.sha256 == request.hash) && ((certEntry.cn == '*') || (certEntry.cn == request.fqdn))) { hashAlgo = 'sha256'; signkey = certEntry.key; certChain = certEntry.certs; certIndex = i; break; }
|
if ((certEntry.sha256 == request.hash) && ((certEntry.cn == '*') || (certEntry.cn == request.fqdn))) { hashAlgo = 'sha256'; signkey = certEntry.key; certChain = certEntry.certs; certIndex = i; break; }
|
||||||
if ((certEntry.sha1 == request.hash) && ((certEntry.cn == '*') || (certEntry.cn == request.fqdn))) { hashAlgo = 'sha1'; signkey = certEntry.key; certChain = certEntry.certs; certIndex = i; break; }
|
if ((certEntry.sha1 == request.hash) && ((certEntry.cn == '*') || (certEntry.cn == request.fqdn))) { hashAlgo = 'sha1'; signkey = certEntry.key; certChain = certEntry.certs; certIndex = i; break; }
|
||||||
}
|
}
|
||||||
if (signkey == null) return { 'action': 'acmactivate', 'error': 2, 'errorText': 'No signing certificate found' }; // Did not find a match.
|
if (signkey == null) return { 'action': 'acmactivate', 'error': 2, 'errorText': "No signing certificate found." }; // Did not find a match.
|
||||||
|
|
||||||
// If the matching certificate is a root cert, issue a leaf cert that matches the fqdn
|
// If the matching certificate is a root cert, issue a leaf cert that matches the fqdn
|
||||||
if (domain.amtacmactivation.certs[certIndex].cn == '*') return { 'action': 'acmactivate', 'error': 3, 'errorText': "Unsupported activation" }; // TODO: Add support for this mode
|
if (domain.amtacmactivation.certs[certIndex].cn == '*') return { 'action': 'acmactivate', 'error': 3, 'errorText': "Unsupported activation." }; // TODO: Add support for this mode
|
||||||
|
|
||||||
// Setup both nonces, ready to be signed
|
// Setup both nonces, ready to be signed
|
||||||
const mcNonce = Buffer.from(obj.crypto.randomBytes(20), 'binary');
|
const mcNonce = Buffer.from(obj.crypto.randomBytes(20), 'binary');
|
||||||
@ -59,10 +59,10 @@ module.exports.CertificateOperations = function (parent) {
|
|||||||
var signer = obj.crypto.createSign(hashAlgo);
|
var signer = obj.crypto.createSign(hashAlgo);
|
||||||
signer.update(Buffer.concat([fwNonce, mcNonce]));
|
signer.update(Buffer.concat([fwNonce, mcNonce]));
|
||||||
signature = signer.sign(signkey, 'base64');
|
signature = signer.sign(signkey, 'base64');
|
||||||
} catch (ex) { return { 'action': 'acmactivate', 'error': 4, 'errorText': "Unable to perform signature" }; }
|
} catch (ex) { return { 'action': 'acmactivate', 'error': 4, 'errorText': "Unable to perform signature." }; }
|
||||||
|
|
||||||
// Log the activation request, logging is a required step for activation.
|
// Log the activation request, logging is a required step for activation.
|
||||||
if (obj.logAmtActivation(domain, { time: new Date(), action: 'acmactivate', 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, tag: request.tag, name: request.name }) == false) return { 'action': 'acmactivate', 'error': 5, 'errorText': 'Unable to log operation' };
|
if (obj.logAmtActivation(domain, { time: new Date(), action: 'acmactivate', 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, tag: request.tag, name: request.name }) == false) return { 'action': 'acmactivate', 'error': 5, 'errorText': "Unable to log operation." };
|
||||||
|
|
||||||
// Return the signature with the computed account password hash
|
// 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 };
|
return { 'action': 'acmactivate', 'signature': signature, 'password': obj.crypto.createHash('md5').update(user + ':' + request.realm + ':' + pass).digest('hex'), 'nonce': mcNonce.toString('base64'), 'certs': certChain };
|
||||||
|
@ -277,7 +277,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||||||
return packet_len;
|
return packet_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.onWebSocketConnection = function (socket) {
|
obj.onWebSocketConnection = function (socket, req) {
|
||||||
connectionCount++;
|
connectionCount++;
|
||||||
// connType: 0 = CIRA, 1 = Relay, 2 = LMS
|
// connType: 0 = CIRA, 1 = Relay, 2 = LMS
|
||||||
socket.tag = { first: true, connType: 0, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], websocket: true, socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
socket.tag = { first: true, connType: 0, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], websocket: true, socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||||
@ -288,6 +288,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||||||
socket.ControlMsg = function ControlMsg(message) { return ControlMsg.parent.SendJsonControl(ControlMsg.conn, message); }
|
socket.ControlMsg = function ControlMsg(message) { return ControlMsg.parent.SendJsonControl(ControlMsg.conn, message); }
|
||||||
socket.ControlMsg.parent = obj;
|
socket.ControlMsg.parent = obj;
|
||||||
socket.ControlMsg.conn = socket;
|
socket.ControlMsg.conn = socket;
|
||||||
|
socket.remoteAddr = req.clientIp;
|
||||||
|
socket.remotePort = socket._socket.remotePort;
|
||||||
parent.debug('mps', "New CIRA websocket connection");
|
parent.debug('mps', "New CIRA websocket connection");
|
||||||
|
|
||||||
socket.on('message', function (data) {
|
socket.on('message', function (data) {
|
||||||
@ -330,6 +332,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||||||
socket.ControlMsg = function ControlMsg(message) { return ControlMsg.parent.SendJsonControl(ControlMsg.conn, message); }
|
socket.ControlMsg = function ControlMsg(message) { return ControlMsg.parent.SendJsonControl(ControlMsg.conn, message); }
|
||||||
socket.ControlMsg.parent = obj;
|
socket.ControlMsg.parent = obj;
|
||||||
socket.ControlMsg.conn = socket;
|
socket.ControlMsg.conn = socket;
|
||||||
|
socket.remoteAddr = cleanRemoteAddr(socket.remoteAddress);
|
||||||
|
//socket.remotePort is already present, no need to set it.
|
||||||
socket.setEncoding('binary');
|
socket.setEncoding('binary');
|
||||||
parent.debug('mps', "New CIRA connection");
|
parent.debug('mps', "New CIRA connection");
|
||||||
|
|
||||||
@ -1225,6 +1229,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||||||
|
|
||||||
function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
|
function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
|
||||||
|
|
||||||
|
// Clean a IPv6 address that encodes a IPv4 address
|
||||||
|
function cleanRemoteAddr(addr) { if (typeof addr != 'string') { return null; } if (addr.indexOf('::ffff:') == 0) { return addr.substring(7); } else { return addr; } }
|
||||||
|
|
||||||
// Example, this will add a file to stream, served 2 times max and 3 minutes max.
|
// Example, this will add a file to stream, served 2 times max and 3 minutes max.
|
||||||
//obj.addHttpFileResponse('/a.png', 'c:\\temp\\MC2-LetsEncrypt.png', 2, 3);
|
//obj.addHttpFileResponse('/a.png', 'c:\\temp\\MC2-LetsEncrypt.png', 2, 3);
|
||||||
|
|
||||||
|
@ -4850,7 +4850,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
||||||
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
||||||
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
||||||
obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.mpsserver.onWebSocketConnection(ws); })
|
obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.mpsserver.onWebSocketConnection(ws, req); })
|
||||||
obj.app.get(url + 'webrelay.ashx', function (req, res) { res.send('Websocket connection expected'); });
|
obj.app.get(url + 'webrelay.ashx', function (req, res) { res.send('Websocket connection expected'); });
|
||||||
obj.app.get(url + 'health.ashx', function (req, res) { res.send('ok'); }); // TODO: Perform more server checking.
|
obj.app.get(url + 'health.ashx', function (req, res) { res.send('ok'); }); // TODO: Perform more server checking.
|
||||||
obj.app.ws(url + 'webrelay.ashx', function (ws, req) { PerformWSSessionAuth(ws, req, false, handleRelayWebSocket); });
|
obj.app.ws(url + 'webrelay.ashx', function (ws, req) { PerformWSSessionAuth(ws, req, false, handleRelayWebSocket); });
|
||||||
|
Loading…
Reference in New Issue
Block a user