Improved MeshCmd, added audit log support.

This commit is contained in:
Ylian Saint-Hilaire 2018-03-20 17:48:03 -07:00
parent b831f097b8
commit 2f3a02d1fd
10 changed files with 107 additions and 78 deletions

Binary file not shown.

Binary file not shown.

View File

@ -91,7 +91,7 @@ function run(argv) {
//console.log('addedModules = ' + JSON.stringify(addedModules));
var actionpath = 'meshaction.txt';
if (args.actionfile != null) { actionpath = args.actionfile; }
var actions = ['HELP', 'ROUTE', 'AMTLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER'];
var actions = ['HELP', 'ROUTE', 'AMTLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG'];
// Load the action file
var actionfile = null;
@ -142,6 +142,7 @@ function run(argv) {
console.log('\r\nValid local or remote actions:');
console.log(' MeshCommander - Launch a local MeshCommander web server.');
console.log(' AmtUUID - Show Intel AMT unique identifier.');
console.log(' AmtAuditLog - Show the Intel AMT audit log.');
console.log(' AmtLoadWebApp - Load MeshCommander in Intel AMT 11.6+ firmware.');
console.log(' AmtClearWebApp - Clear everything from Intel AMT web storage.');
console.log(' AmtStorageState - Show contents of the Intel AMT web storage.');
@ -230,6 +231,14 @@ function run(argv) {
console.log('This action launched a local web server that hosts MeshCommander, a Intel AMT management console.');
console.log('\r\nPossible arguments:\r\n');
console.log(' --localport [port] Local port used for the web server, 3000 is default.');
} else if (action == 'amtauditlog') {
console.log('AmtAuditLog action will fetch the local or remote audit log. If used localy, no username/password is required. Example usage:\r\n\r\n meshcmd amtauditlog --host 1.2.3.4 --user admin --pass mypassword --tls --output audit.json');
console.log('\r\nPossible arguments:\r\n');
console.log(' --output [filename] The output file for the Intel AMT state in JSON format.');
console.log(' --host [hostname] The IP address or DNS name of Intel AMT, 127.0.0.1 is default.');
console.log(' --user [username] The Intel AMT login username, admin is default.');
console.log(' --pass [password] The Intel AMT login password.');
console.log(' --tls Specifies that TLS must be used.');
} else {
actions.shift();
console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.');
@ -373,15 +382,61 @@ function run(argv) {
// Deactivate CCM
debug(1, "Settings: " + JSON.stringify(settings));
deactivateCCM();
} else if (settings.action == 'meshcommander') {
// Start MeshCommander
} else if (settings.action == 'meshcommander') { // Start MeshCommander
startMeshCommander();
} else if (settings.action == 'amtauditlog') { // Read the Intel AMT audit log
if (settings.hostname != null) {
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
} else { settings.hostname = '127.0.0.1'; }
readAmtAuditLog();
} else {
console.log('Invalid \"action\" specified.'); exit(1); return;
}
}
//
// Intel AMT Audit Log
//
function readAmtAuditLog() {
// See if MicroLMS needs to be started
if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) {
settings.noconsole = true; startLms(readAmtAuditLogEx);
} else {
readAmtAuditLogEx(9999);
}
}
function readAmtAuditLogEx(x) {
if (x == 9999) {
var transport = require('amt-wsman-duk');
var wsman = require('amt-wsman');
var amt = require('amt');
wsstack = new wsman(transport, settings.hostname, settings.tls ? 16993 : 16992, settings.username, settings.password, settings.tls);
amtstack = new amt(wsstack);
amtstack.GetAuditLog(readAmtAuditLogEx2);
} else {
osamtstack.GetAuditLog(readAmtAuditLogEx2);
}
}
function readAmtAuditLogEx2(stack, response, status) {
if (status != 200) {
console.log('Unable to get audit log, status = ' + status + '.');
} else {
var out = '';
for (var i in response) {
var name = ((response[i].Initiator != '')?(response[i].Initiator + ': '):'')
out += (response[i].Time + ' - ' + name + response[i].Event + '\r\n');
}
if (settings.output == null) { console.log(out); } else { var file = fs.openSync(settings.output, 'w'); fs.writeSync(file, new Buffer(out, 'utf8')); fs.closeSync(file); }
}
exit(1);
}
//
// MeshCommander local web server
//
@ -397,27 +452,18 @@ function startMeshCommander() {
var http = require('http');
webServer = http.createServer();
webServer.listen(settings.localport);
webServer.wsList = {};
webServer.wsListIndex = 0;
webServer.on('upgrade', function (req, socket, head) {
//console.log("WebSocket for " + req.url.split('?')[0]);
switch (req.url.split('?')[0]) {
case '/webrelay.ashx': // MeshCommander relay channel
var ws = socket.upgradeWebSocket();
socket.ws = ws;
ws.wsIndex = ++webServer.wsListIndex;
webServer.wsList[ws.wsIndex] = ws;
ws.pause();
// When data is received from the web socket, forward the data into the associated TCP connection.
// If the TCP connection is pending, buffer up the data until it connects.
ws.on('data', function (data) {
//console.log('Data relay --> ' + data.length + ': ' + data.toString() + '\r\n');
ws.forwardclient.write(data); // Forward data to the associated TCP connection.
});
// If the web socket is closed, close the associated TCP connection.
ws.on('close', function (req) {
//console.log('Closed websocket.');
if (ws.forwardclient) { try { ws.forwardclient.destroy(); } catch (e) { } }
});
// We got a new web socket connection, initiate a TCP connection to the target Intel AMT host/port.
var webargs = parseUrlArguments(req.url);
if (webargs.p) { webargs.p = parseInt(webargs.p); }
@ -429,36 +475,16 @@ function startMeshCommander() {
// If this is TCP (without TLS) set a normal TCP socket
var net = require('net');
ws.forwardclient = net.connect({ host: webargs.host, port: webargs.port })
ws.forwardclient.on('connect', function () { this.pipe(this.ws); this.ws.pipe(this); });
ws.forwardclient.ws = ws;
ws.forwardclient.on('connect', function () { this.ws.resume(); });
} else {
// If TLS is going to be used, setup a TLS socket
var tls = require('tls');
var tlsoptions = { host: webargs.host, port: webargs.port, secureProtocol: ((webargs.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), rejectUnauthorized: false };
ws.forwardclient = tls.connect(tlsoptions, function () { this.ws.resume(); });
ws.forwardclient = tls.connect(tlsoptions, function () { this.pipe(this.ws); this.ws.pipe(this); });
ws.forwardclient.ws = ws;
}
// When we receive data on the TCP connection, forward it back into the web socket connection.
ws.forwardclient.on('data', function (data) {
//console.log('Data relay <-- ' + data.length + ': ' + data.toString() + '\r\n');
try { this.ws.write(data); } catch (e) { }
});
// If the TCP connection closes, disconnect the associated web socket.
ws.forwardclient.on('close', function () {
//console.log('TCP/TLS disconnected.');
try { this.ws.end(); } catch (e) { }
try { this.end(); } catch (e) { }
});
// If the TCP connection causes an error, disconnect the associated web socket.
ws.forwardclient.on('error', function (err) {
//console.log('TCP/TLS disconnected with error', err);
try { this.ws.end(); } catch (e) { }
try { this.end(); } catch (e) { }
});
break;
default:
socket.end();
@ -1129,5 +1155,11 @@ function parseUrlArguments(url) {
return r;
}
// Remove a element from a array
function removeItemFromArray(array, element) {
const index = array.indexOf(element);
if (index !== -1) { array.splice(index, 1); }
}
// Run MeshCmd
try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); }

View File

@ -75,10 +75,10 @@ function createMeshCore(agent) {
// Try to load up the MEI module
try {
var amtMeiLib = require('amt-mei');
amtMeiConnected = 1;
amtMei = new amtMeiLib();
amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); });
amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); });
amtMeiConnected = 2;
//amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); });
} catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
// Try to load up the WIFI scanner
@ -869,11 +869,11 @@ function createMeshCore(agent) {
break;
}
case 'selfinfo': { // Return self information block
buildSelfInfo(function (info) { sendConsoleText(objToString(info, 0, ' '), sessionid); });
buildSelfInfo(function (info) { sendConsoleText(objToString(info, 0, ' ', true), sessionid); });
break;
}
case 'args': { // Displays parsed command arguments
response = 'args ' + objToString(args, 0, ' ');
response = 'args ' + objToString(args, 0, ' ', true);
break;
}
case 'print': { // Print a message on the mesh agent console, does nothing when running in the background
@ -1045,7 +1045,7 @@ function createMeshCore(agent) {
case 'amt': { // Show Intel AMT status
getAmtInfo(function (state) {
var resp = 'Intel AMT not detected.';
if (state != null) { resp = objToString(state, 0, ' '); }
if (state != null) { resp = objToString(state, 0, ' ', true); }
sendConsoleText(resp, sessionid);
});
break;
@ -1053,7 +1053,11 @@ function createMeshCore(agent) {
case 'netinfo': { // Show network interface information
//response = objToString(mesh.NetInfo, 0, ' ');
var interfaces = require('os').networkInterfaces();
response = objToString(interfaces, 0, ' ');
response = objToString(interfaces, 0, ' ', true);
break;
}
case 'netinfo2': { // Show network interface information
response = objToString(mesh.NetInfo, 0, ' ', true);
break;
}
case 'wakeonlan': { // Send wake-on-lan
@ -1215,7 +1219,7 @@ function createMeshCore(agent) {
amtMei.getVersion(function (val) { amtMeiTmpState.Versions = {}; for (var version in val.Versions) { amtMeiTmpState.Versions[val.Versions[version].Description] = val.Versions[version].Version; } });
amtMei.getProvisioningMode(function (result) { amtMeiTmpState.ProvisioningMode = result.mode; });
amtMei.getProvisioningState(function (result) { amtMeiTmpState.ProvisioningState = result.state; });
amtMei.getEHBCState(function (result) { if (result.EHBC == true) { amtMeiTmpState.Flags += 1; } });
amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } });
amtMei.getControlMode(function (result) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } });
//amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; });
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } if (func != null) { func(amtMeiTmpState); } });

View File

@ -18,7 +18,6 @@ var Q = require('queue');
function amt_heci() {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci');

View File

@ -633,7 +633,7 @@ function AmtStackCreateService(wsmanStack) {
2003: 'Security Audit Log Enabled',
2004: 'Security Audit Log Exported',
2005: 'Security Audit Log Recovered',
2100: 'Intel&reg; ME Time Set',
2100: 'Intel(R) ME Time Set',
2200: 'TCPIP Parameters Set',
2201: 'Host Name Set',
2202: 'Domain Name Set',
@ -742,12 +742,12 @@ function AmtStackCreateService(wsmanStack) {
}
if (x['InitiatorType'] == 2) {
// Local
x['Initiator'] = '<i>Local</i>';
x['Initiator'] = 'Local';
ptr = 5;
}
if (x['InitiatorType'] == 3) {
// KVM Default Port
x['Initiator'] = '<i>KVM Default Port</i>';
x['Initiator'] = 'KVM Default Port';
ptr = 5;
}

View File

@ -290,11 +290,8 @@ function lme_heci(options) {
var notify = null;
try { notify = xmlParser.ParseWsman(httpData); } catch (e) { }
// Translate the event
var notifyString = _lmsNotifyToString(notify);
// Event the http data
if (notify != null) { this.LMS.emit('notify', notify, channel.options, notifyString); }
if (notify != null) { this.LMS.emit('notify', notify, channel.options, _lmsNotifyToString(notify), _lmsNotifyToCode(notify)); }
// Send channel close
var buffer = Buffer.alloc(5);
@ -437,6 +434,13 @@ function parseHttp(httpData) {
return null;
}
function _lmsNotifyToCode(notify) {
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
var msgid = notify.Body.MessageID;
try { msgid += '-' + notify.Body.MessageArguments[0]; } catch (e) { }
return msgid;
}
function _lmsNotifyToString(notify) {
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
var msgid = notify.Body.MessageID;
@ -520,7 +524,7 @@ var lmsEvents = {
"iAMT0055-0": "User Notification Alert - Provisioning state change notification - Pre-configuration.",
"iAMT0055-1": "User Notification Alert - Provisioning state change notification - In configuration.",
"iAMT0055-2": "User Notification Alert - Provisioning state change notification - Post-configuration.",
"iAMT0055-3": "User Notification Alert - Provisioning state change notification - unprovision process has started.",
"iAMT0055-3": "User Notification Alert - Provisioning state change notification - Unprovision process has started.",
"iAMT0056": "User Notification Alert - System Defense change notification.",
"iAMT0057": "User Notification Alert - Network State change notification.",
"iAMT0058": "User Notification Alert - Remote Access change notification.",

View File

@ -18,24 +18,20 @@ var Q = require('queue');
function amt_heci() {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci');
this._ObjectID = "pthi";
this._rq = new Q();
this._setupPTHI = function _setupPTHI()
{
this._setupPTHI = function _setupPTHI() {
this._amt = heci.create();
this._amt.BiosVersionLen = 65;
this._amt.UnicodeStringLen = 20;
this._amt.Parent = this;
this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); });
this._amt.on('connect', function _amtOnConnect()
{
this.on('data', function _amtOnData(chunk)
{
this._amt.on('connect', function _amtOnConnect() {
this.on('data', function _amtOnData(chunk) {
//console.log("Received: " + chunk.length + " bytes");
var header = this.Parent.getCommand(chunk);
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
@ -47,14 +43,12 @@ function amt_heci() {
params.unshift(header);
callback.apply(this.Parent, params);
if(this.Parent._rq.isEmpty())
{
if (this.Parent._rq.isEmpty()) {
// No More Requests, we can close PTHI
this.Parent._amt.disconnect();
this.Parent._amt = null;
}
else
{
else {
// Send the next request
this.write(this.Parent._rq.peekQueue().send);
}
@ -79,10 +73,9 @@ function amt_heci() {
var header = Buffer.from('010100000000000000000000', 'hex');
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args , send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]]))});
this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args, send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]])) });
if(!this._amt)
{
if (!this._amt) {
this._setupPTHI();
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
}
@ -94,7 +87,7 @@ function amt_heci() {
this.sendCommand(26, null, function (header, fn, opt) {
if (header.Status == 0) {
var i, CodeVersion = header.Data, val = { BiosVersion: CodeVersion.slice(0, this._amt.BiosVersionLen), Versions: [] }, v = CodeVersion.slice(this._amt.BiosVersionLen + 4);
for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen) ; ++i) {
for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen); ++i) {
val.Versions[i] = { Description: v.slice(2, v.readUInt16LE(0) + 2).toString(), Version: v.slice(4 + this._amt.UnicodeStringLen, 4 + this._amt.UnicodeStringLen + v.readUInt16LE(2 + this._amt.UnicodeStringLen)).toString() };
v = v.slice(4 + (2 * this._amt.UnicodeStringLen));
}

View File

@ -563,15 +563,7 @@
<div id="d7meshkvm">
<h4 style="width:100%;border-bottom:1px solid gray">Mesh Agent Remote Desktop</h4>
<div style="margin:3px 0 3px 0">
<select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl">
<option value=50>50%</option>
<option value=40>40%</option>
<option selected=selected value=30>30%</option>
<option value=20>20%</option>
<option value=10>10%</option>
<option value=5>5%</option>
<option value=1>1%</option>
</select>
<select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl"></select>
<div style="height:20px">Quality</div>
</div>
<div style="margin:3px 0 3px 0">
@ -3075,9 +3067,13 @@
}
function applyDesktopSettings() {
var r = '', ops = (features & 512)?[100,80,50,40,30,20,10,5,1]:[50,40,30,20,10,5,1];
for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
QH('d7bitmapquality', r);
d7desktopmode.value = desktopsettings.encoding;
d7showfocus.checked = desktopsettings.showfocus;
d7showcursor.checked = desktopsettings.showmouse;
d7bitmapquality.value = 40; // Default value
d7bitmapquality.value = desktopsettings.quality;
d7bitmapscaling.value = desktopsettings.scaling;
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (desktop.state != 0) && (desktopsettings.showfocus));

View File

@ -682,6 +682,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
if ((obj.parent.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName != 'un-configured') && (obj.args.lanonly != true)) { features += 64; } // Email invites
if (obj.args.webrtc == true) { features += 128; } // Enable WebRTC (Default false for now)
if (obj.args.clickonce !== false) { features += 256; } // Enable ClickOnce (Default true)
if (obj.args.allowhighqualitydesktop == true) { features += 512; } // Enable AllowHighQualityDesktop (Default false)
// Send the master web application
if ((!obj.args.user) && (obj.args.nousers != true) && (nologout == false)) { logoutcontrol += ' <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>'; } // If a default user is in use or no user mode, don't display the logout button