1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-03-09 15:40:18 +00:00

Improved MeshAgent and MeshCmd.

This commit is contained in:
Ylian Saint-Hilaire 2018-01-25 16:12:53 -08:00
parent c3144c097a
commit a5e5611cbe
17 changed files with 198 additions and 154 deletions

View file

@ -467,18 +467,18 @@ function AmtStackCreateService(wsmanStack) {
obj.AMT_MessageLog_PositionToFirstRecord(_GetMessageLog0, [func, tag, []]);
}
function _GetMessageLog0(stack, name, responses, status, tag) {
if (status != 200 || responses.Body["ReturnValue"] != '0') { tag[0](obj, null, tag[2]); return; }
if (status != 200 || responses.Body["ReturnValue"] != '0') { tag[0](obj, null, tag[2], status); return; }
obj.AMT_MessageLog_GetRecords(responses.Body["IterationIdentifier"], 390, _GetMessageLog1, tag);
}
function _GetMessageLog1(stack, name, responses, status, tag) {
if (status != 200 || responses.Body["ReturnValue"] != '0') { tag[0](obj, null, tag[2]); return; }
if (status != 200 || responses.Body["ReturnValue"] != '0') { tag[0](obj, null, tag[2], status); return; }
var i, j, x, e, AmtMessages = tag[2], t = new Date(), TimeStamp, ra = responses.Body["RecordArray"];
if (typeof ra === 'string') { responses.Body["RecordArray"] = [responses.Body["RecordArray"]]; }
for (i in ra) {
e = Buffer.from(ra[i], 'base64');
if (e != null) {
TimeStamp = ReadIntXBuf(e, 0);
TimeStamp = ReadIntX(e, 0);
if ((TimeStamp > 0) && (TimeStamp < 0xFFFFFFFF)) {
x = { 'DeviceAddress': e[4], 'EventSensorType': e[5], 'EventType': e[6], 'EventOffset': e[7], 'EventSourceType': e[8], 'EventSeverity': e[9], 'SensorNumber': e[10], 'Entity': e[11], 'EntityInstance': e[12], 'EventData': [], 'Time': new Date((TimeStamp + (t.getTimezoneOffset() * 60)) * 1000) };
for (j = 13; j < 21; j++) { x['EventData'].push(e[j]); }
@ -678,17 +678,17 @@ function AmtStackCreateService(wsmanStack) {
// TODO: Just put some of them here, but many more still need to be added, helpful link here:
// https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=WordDocuments%2Fsecurityadminevents.htm
obj.GetAuditLogExtendedDataStr = function (id, data) {
if ((id == 1602 || id == 1604) && data.charCodeAt(0) == 0) { return data.substring(2, 2 + data.charCodeAt(1)); } // ACL Entry Added/Removed (Digest)
if (id == 1603) { if (data.charCodeAt(1) == 0) { return data.substring(3); } return null; } // ACL Entry Modified
if (id == 1605) { return ["Invalid ME access", "Invalid MEBx access"][data.charCodeAt(0)]; } // ACL Access with Invalid Credentials
if (id == 1606) { var r = ["Disabled", "Enabled"][data.charCodeAt(0)]; if (data.charCodeAt(1) == 0) { r += ", " + data.substring(3); } return r;} // ACL Entry State
if (id == 1607) { return "Remote " + ["NoAuth", "ServerAuth", "MutualAuth"][data.charCodeAt(0)] + ", Local " + ["NoAuth", "ServerAuth", "MutualAuth"][data.charCodeAt(1)]; } // TLS State Changed
if (id == 1617) { return obj.RealmNames[ReadInt(data, 0)] + ", " + ["NoAuth", "Auth", "Disabled"][data.charCodeAt(4)]; } // Set Realm Authentication Mode
if (id == 1619) { return ["BIOS", "MEBx", "Local MEI", "Local WSMAN", "Remote WSAMN"][data.charCodeAt(0)]; } // Intel AMT Unprovisioning Started
if ((id == 1602 || id == 1604) && data[0] == 0) { return data.splice(2, 2 + data[1]).toString(); } // ACL Entry Added/Removed (Digest)
if (id == 1603) { if (data[1] == 0) { return data.splice(3).toString(); } return null; } // ACL Entry Modified
if (id == 1605) { return ["Invalid ME access", "Invalid MEBx access"][data[0]]; } // ACL Access with Invalid Credentials
if (id == 1606) { var r = ["Disabled", "Enabled"][data[0]]; if (data[1] == 0) { r += ", " + data[3]; } return r; } // ACL Entry State
if (id == 1607) { return "Remote " + ["NoAuth", "ServerAuth", "MutualAuth"][data[0]] + ", Local " + ["NoAuth", "ServerAuth", "MutualAuth"][data[1]]; } // TLS State Changed
if (id == 1617) { return obj.RealmNames[ReadInt(data, 0)] + ", " + ["NoAuth", "Auth", "Disabled"][data[4]]; } // Set Realm Authentication Mode
if (id == 1619) { return ["BIOS", "MEBx", "Local MEI", "Local WSMAN", "Remote WSAMN"][data[0]]; } // Intel AMT Unprovisioning Started
if (id == 1900) { return "From " + ReadShort(data, 0) + "." + ReadShort(data, 2) + "." + ReadShort(data, 4) + "." + ReadShort(data, 6) + " to " + ReadShort(data, 8) + "." + ReadShort(data, 10) + "." + ReadShort(data, 12) + "." + ReadShort(data, 14); } // Firmware Updated
if (id == 2100) { var t4 = new Date(); t4.setTime(ReadInt(data, 0) * 1000 + (new Date().getTimezoneOffset() * 60000)); return t4.toLocaleString(); } // Intel AMT Time Set
if (id == 3000) { return "From " + ["None", "KVM", "All"][data.charCodeAt(0)] + " to " + ["None", "KVM", "All"][data.charCodeAt(1)]; } // Opt-In Policy Change
if (id == 3001) { return ["Success", "Failed 3 times"][data.charCodeAt(0)]; } // Send Consent Code Event
if (id == 3000) { return "From " + ["None", "KVM", "All"][data[0]] + " to " + ["None", "KVM", "All"][data[1]]; } // Opt-In Policy Change
if (id == 3001) { return ["Success", "Failed 3 times"][data[0]]; } // Send Consent Code Event
return null;
}
@ -697,22 +697,15 @@ function AmtStackCreateService(wsmanStack) {
}
function MakeToArray(v) { if (!v || v == null || typeof v == 'object') return v; return [v]; }
function ReadShort(v, p) { return (v.charCodeAt(p) << 8) + v.charCodeAt(p + 1); }
function ReadInt(v, p) { return (v.charCodeAt(p) * 0x1000000) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3); } // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
function ReadIntX(v, p) { return (v.charCodeAt(p + 3) * 0x1000000) + (v.charCodeAt(p + 2) << 16) + (v.charCodeAt(p + 1) << 8) + v.charCodeAt(p); }
function ReadIntXBuf(v, p) { return (v[p + 3] * 0x1000000) + (v[p + 2] << 16) + (v[p + 1] << 8) + v[p]; }
function ReadShort(v, p) { return (v[p] << 8) + v[p + 1]; }
function ReadInt(v, p) { return (v[p] * 0x1000000) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; } // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
function ReadIntX(v, p) { return (v[p + 3] * 0x1000000) + (v[p + 2] << 16) + (v[p + 1] << 8) + v[p]; }
function btoa(x) { return Buffer.from(x).toString('base64'); }
function atob(x) {
var z = null;
try {
z = Buffer.from(x, 'base64').toString();
} catch (e) { console.log(e); }
return z;
}
function atob(x) { var z = null; try { z = Buffer.from(x, 'base64').toString(); } catch (e) { console.log(e); } return z; }
function _GetAuditLog0(stack, name, responses, status, tag) {
if (status != 200) { tag[0](obj, [], status); return; }
var ptr, i, e, x, r = tag[1], t = new Date(), TimeStamp;
var ptr, i, e, es, x, r = tag[1], t = new Date(), TimeStamp;
if (responses.Body['RecordsReturned'] > 0) {
responses.Body['EventRecords'] = MakeToArray(responses.Body['EventRecords']);
@ -720,11 +713,13 @@ function AmtStackCreateService(wsmanStack) {
for (i in responses.Body['EventRecords']) {
e = null;
try {
e = atob(responses.Body['EventRecords'][i]);
} catch (e) {
console.log(e + " " + responses.Body['EventRecords'][i])
es = atob(responses.Body['EventRecords'][i]);
e = new Buffer(es);
} catch (ex) {
console.log(ex + " " + responses.Body['EventRecords'][i])
}
x = { 'AuditAppID': ReadShort(e, 0), 'EventID': ReadShort(e, 2), 'InitiatorType': e.charCodeAt(4) };
x = { 'AuditAppID': ReadShort(e, 0), 'EventID': ReadShort(e, 2), 'InitiatorType': e[4] };
x['AuditApp'] = _AmtAuditStringTable[x['AuditAppID']];
x['Event'] = _AmtAuditStringTable[(x['AuditAppID'] * 100) + x['EventID']];
if (!x['Event']) x['Event'] = '#' + x['EventID'];
@ -732,15 +727,15 @@ function AmtStackCreateService(wsmanStack) {
// Read and process the initiator
if (x['InitiatorType'] == 0) {
// HTTP digest
var userlen = e.charCodeAt(5);
x['Initiator'] = e.substring(6, 6 + userlen);
var userlen = e[5];
x['Initiator'] = e.slice(6, 6 + userlen).toString();
ptr = 6 + userlen;
}
if (x['InitiatorType'] == 1) {
// Kerberos
x['KerberosUserInDomain'] = ReadInt(e, 5);
var userlen = e.charCodeAt(9);
x['Initiator'] = GetSidString(e.substring(10, 10 + userlen));
var userlen = e[9];
x['Initiator'] = GetSidString(e.slice(10, 10 + userlen));
ptr = 10 + userlen;
}
if (x['InitiatorType'] == 2) {
@ -753,23 +748,23 @@ function AmtStackCreateService(wsmanStack) {
x['Initiator'] = '<i>KVM Default Port</i>';
ptr = 5;
}
// Read timestamp
TimeStamp = ReadInt(e, ptr);
x['Time'] = new Date((TimeStamp + (t.getTimezoneOffset() * 60)) * 1000);
ptr += 4;
// Read network access
x['MCLocationType'] = e.charCodeAt(ptr++);
var netlen = e.charCodeAt(ptr++);
x['NetAddress'] = e.substring(ptr, ptr + netlen);
x['MCLocationType'] = e[ptr++];
var netlen = e[ptr++];
x['NetAddress'] = e.slice(ptr, ptr + netlen).toString();
// Read extended data
ptr += netlen;
var exlen = e.charCodeAt(ptr++);
x['Ex'] = e.substring(ptr, ptr + exlen);
var exlen = e[ptr++];
x['Ex'] = e.slice(ptr, ptr + exlen);
x['ExStr'] = obj.GetAuditLogExtendedDataStr((x['AuditAppID'] * 100) + x['EventID'], x['Ex']);
r.push(x);
}
}

View file

@ -33,6 +33,7 @@ function CreateWsmanComm(host, port, user, pass, tls, extra) {
obj.pass = pass;
obj.tls = tls;
obj.digest = null;
obj.RequestCount = 0;
// Private method
// pri = priority, if set to 1, the call is high priority and put on top of the stack.
@ -58,13 +59,16 @@ function CreateWsmanComm(host, port, user, pass, tls, extra) {
obj.PerformAjaxEx = function (postdata, callback, tag, url, action) {
if (obj.FailAllError != 0) { if (obj.FailAllError != 999) { obj.gotNextMessagesError({ status: obj.FailAllError }, 'error', null, [postdata, callback, tag]); } return; }
if (!postdata) postdata = "";
// console.log("SEND: " + postdata); // DEBUG
//console.log("SEND: " + postdata); // DEBUG
// We are in a DukTape environement
if (obj.digest == null) { obj.digest = require('http-digest').create(obj.user, obj.pass); obj.digest.http = require('http'); }
var request = { protocol: (obj.tls == 1 ? 'https:' : 'http:'), method: 'POST', host: obj.host, path: '/wsman', port: obj.port };
var req = obj.digest.request(request,
function (response) {
var request = { protocol: (obj.tls == 1 ? 'https:' : 'http:'), method: 'POST', host: obj.host, path: '/wsman', port: obj.port, rejectUnauthorized: false, checkServerIdentity: function (cert) { console.log('checkServerIdentity', JSON.stringify(cert)); } };
var req = obj.digest.request(request);
//console.log('Request ' + (obj.RequestCount++));
req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
req.on('response', function (response) {
//console.log('Response: ' + response.statusCode);
if (response.statusCode != 200) {
console.log('ERR:' + JSON.stringify(response));
obj.gotNextMessagesError({ status: response.statusCode }, 'error', null, [postdata, callback, tag]);
@ -74,11 +78,11 @@ function CreateWsmanComm(host, port, user, pass, tls, extra) {
response.on('end', function () { obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); });
}
});
req.on('error', function (e) { console.log(JSON.stringify(e)); obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
// Send POST body, this work with binary.
req.write(postdata);
req.end();
obj.ActiveAjaxCount++;
return req;
}
@ -101,7 +105,7 @@ function CreateWsmanComm(host, port, user, pass, tls, extra) {
obj.ActiveAjaxCount--;
if (obj.FailAllError == 999) return;
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
// if (s != 200) { console.log("ERROR, status=" + status + "\r\n\r\nreq=" + callArgs[0]); } // Debug: Display the request & response if something did not work.
//if (status != 200) { console.log("ERROR, status=" + status + "\r\n\r\nreq=" + callArgs[0]); } // Debug: Display the request & response if something did not work.
if (obj.FailAllError != 999) { callArgs[1]({ Header: { HttpError: request.status } }, request.status, callArgs[2]); }
obj.PerformNextAjax();
}

View file

@ -16,6 +16,7 @@ limitations under the License.
var MemoryStream = require('MemoryStream');
var lme_id = 0;
var lme_port_offset = 0; // Debug: Set this to "-100" to bind to 16892 & 16893 and IN_ADDRANY. This is for LMS debugging.
var APF_DISCONNECT = 1;
@ -68,9 +69,7 @@ function stream_bufferedWrite() {
return (this._readCheckImmediate == undefined);
};
this.write = function (chunk) {
for (var args in arguments) {
if (typeof (arguments[args]) == 'function') { this.once('drain', arguments[args]); break; }
}
for (var args in arguments) { if (typeof (arguments[args]) == 'function') { this.once('drain', arguments[args]); break; } }
var tmp = Buffer.alloc(chunk.length);
chunk.copy(tmp);
this.buffer.push({ offset: 0, data: tmp });
@ -90,8 +89,7 @@ function stream_bufferedWrite() {
list.push(this.buffer[0].data.slice(offset, offset + size - bytesRead));
this.buffer[0].offset += (size - bytesRead);
bytesRead += (size - bytesRead);
}
else {
} else {
// Reading the entire thing
list.push(this.buffer[0].data.slice(offset));
bytesRead += len;
@ -101,12 +99,9 @@ function stream_bufferedWrite() {
this._readCheckImmediate = setImmediate(function (buffered) {
buffered._readCheckImmediate = undefined;
if (buffered.buffer.length == 0) {
// drained
buffered.emit('drain');
}
else {
// not drained
buffered.emit('readable');
buffered.emit('drain'); // Drained
} else {
buffered.emit('readable'); // Not drained
}
}, this);
return (Buffer.concat(list));
@ -114,11 +109,13 @@ function stream_bufferedWrite() {
}
function lme_heci() {
function lme_heci(options) {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
if (options.debug == true) { lme_port_offset = -100; } // LMS debug mode
var heci = require('heci');
this.INITIAL_RXWINDOW_SIZE = 4096;
@ -147,8 +144,7 @@ function lme_heci() {
outBuffer.write(name.toString(), 5);
this.write(outBuffer);
//console.log('Answering APF_SERVICE_REQUEST');
}
else {
} else {
//console.log('UNKNOWN APF_SERVICE_REQUEST');
}
break;
@ -166,10 +162,14 @@ function lme_heci() {
}
this[name][port] = require('net').createServer();
this[name][port].HECI = this;
this[name][port].listen({ port: port, host: '127.0.0.1' });
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
}
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);
this.HECI.LMS.bindDuplexStream(socket, socket.remoteFamily, socket.localPort - lme_port_offset);
});
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(81, 0);
@ -246,8 +246,7 @@ function lme_heci() {
if (!this.sockets[rChannelId].bufferedStream.isEmpty() && this.sockets[rChannelId].bufferedStream.isWaiting()) {
this.sockets[rChannelId].bufferedStream.emit('readable');
}
}
else {
} else {
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
}
break;
@ -265,8 +264,7 @@ function lme_heci() {
outBuffer.writeUInt32BE(written, 5);
this.HECI.write(outBuffer);
});
}
else {
} else {
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
}
break;
@ -281,8 +279,7 @@ function lme_heci() {
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
buffer.writeUInt32BE(amtId, 1);
this.write(buffer);
}
else {
} else {
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_CLOSE');
}
break;
@ -309,12 +306,10 @@ function lme_heci() {
if (remoteFamily == 'IPv6') {
buffer.writeUInt32BE(3);
buffer.write('::1');
}
else {
} else {
buffer.writeUInt32BE(9);
buffer.write('127.0.0.1');
}
buffer.writeUInt32BE(localPort);
}
this._LME.write(buffer.buffer);