Improved MicroLMS and MeshCmd.

This commit is contained in:
Ylian Saint-Hilaire 2018-01-30 18:23:57 -08:00
parent dd6c66d91d
commit 682573d262
27 changed files with 3640 additions and 98 deletions

View File

@ -69,6 +69,7 @@
<Compile Include="public\scripts\meshcentral.js" />
<Compile Include="redirserver.js" />
<Compile Include="webserver.js" />
<Content Include="LICENSE" />
<Content Include="package.json" />
<Content Include="public\clickonce\minirouter\Application Files\MeshMiniRouter_1_0_0_70\MeshMiniRouter.application" />
<Content Include="public\clickonce\minirouter\Application Files\MeshMiniRouter_1_0_0_70\MeshMiniRouter.exe.config.deploy" />
@ -165,6 +166,7 @@
<Content Include="public\styles\font-awesome\scss\_variables.scss" />
<Content Include="public\styles\style.css" />
<Content Include="readme.txt" />
<Content Include="sample-config.json" />
<Content Include="SourceFileList.txt" />
<Content Include="views\default.handlebars" />
<Content Include="views\download.handlebars" />

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -73,7 +73,7 @@ function createMeshCore(agent) {
// Try to load up the MEI module
try {
var amtMeiLib = require('amt_heci');
var amtMeiLib = require('amt-mei');
amtMeiConnected = 1;
amtMei = new amtMeiLib();
amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); });
@ -82,7 +82,7 @@ function createMeshCore(agent) {
// Try to load up the WIFI scanner
try {
var wifiScannerLib = require('WifiScanner');
var wifiScannerLib = require('wifi-scanner');
wifiScanner = new wifiScannerLib();
wifiScanner.on('accessPoint', function (data) { sendConsoleText(JSON.stringify(data)); });
} catch (e) { wifiScannerLib = null; wifiScanner = null; }
@ -1211,7 +1211,7 @@ function createMeshCore(agent) {
// Launch LMS
try {
var lme_heci = require('lme_heci');
var lme_heci = require('amt-lme');
amtLmsState = 1;
amtLms = new lme_heci();
amtLms.on('error', function (e) { amtLmsState = 0; amtLms = null; });

View File

@ -0,0 +1,420 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var MemoryStream = require('MemoryStream');
var lme_id = 0; // Our next channel identifier
var lme_port_offset = 0; // Debug: Set this to "-100" to bind to 16892 & 16893 and IN_ADDRANY. This is for LMS debugging.
// Documented in: https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/HTMLDocuments/MPSDocuments/Intel%20AMT%20Port%20Forwarding%20Protocol%20Reference%20Manual.pdf
var APF_DISCONNECT = 1;
var APF_SERVICE_REQUEST = 5;
var APF_SERVICE_ACCEPT = 6;
var APF_USERAUTH_REQUEST = 50;
var APF_USERAUTH_FAILURE = 51;
var APF_USERAUTH_SUCCESS = 52;
var APF_GLOBAL_REQUEST = 80;
var APF_REQUEST_SUCCESS = 81;
var APF_REQUEST_FAILURE = 82;
var APF_CHANNEL_OPEN = 90;
var APF_CHANNEL_OPEN_CONFIRMATION = 91;
var APF_CHANNEL_OPEN_FAILURE = 92;
var APF_CHANNEL_WINDOW_ADJUST = 93;
var APF_CHANNEL_DATA = 94;
var APF_CHANNEL_CLOSE = 97;
var APF_PROTOCOLVERSION = 192;
function lme_object() {
this.ourId = ++lme_id;
this.amtId = -1;
this.LME_CHANNEL_STATUS = 'LME_CS_FREE';
this.txWindow = 0;
this.rxWindow = 0;
this.localPort = 0;
this.errorCount = 0;
}
function stream_bufferedWrite() {
var emitterUtils = require('events').inherits(this);
this.buffer = [];
this._readCheckImmediate = undefined;
// Writable Events
emitterUtils.createEvent('close');
emitterUtils.createEvent('drain');
emitterUtils.createEvent('error');
emitterUtils.createEvent('finish');
emitterUtils.createEvent('pipe');
emitterUtils.createEvent('unpipe');
// Readable Events
emitterUtils.createEvent('readable');
this.isEmpty = function () {
return (this.buffer.length == 0);
};
this.isWaiting = function () {
return (this._readCheckImmediate == undefined);
};
this.write = function (chunk) {
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 });
this.emit('readable');
return (this.buffer.length == 0 ? true : false);
};
this.read = function () {
var size = arguments.length == 0 ? undefined : arguments[0];
var bytesRead = 0;
var list = [];
while ((size == undefined || bytesRead < size) && this.buffer.length > 0) {
var len = this.buffer[0].data.length - this.buffer[0].offset;
var offset = this.buffer[0].offset;
if (len > (size - bytesRead)) {
// Only reading a subset
list.push(this.buffer[0].data.slice(offset, offset + size - bytesRead));
this.buffer[0].offset += (size - bytesRead);
bytesRead += (size - bytesRead);
} else {
// Reading the entire thing
list.push(this.buffer[0].data.slice(offset));
bytesRead += len;
this.buffer.shift();
}
}
this._readCheckImmediate = setImmediate(function (buffered) {
buffered._readCheckImmediate = undefined;
if (buffered.buffer.length == 0) {
buffered.emit('drain'); // Drained
} else {
buffered.emit('readable'); // Not drained
}
}, this);
return (Buffer.concat(list));
};
}
function lme_heci(options) {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
emitterUtils.createEvent('notify');
if (options.debug == true) { lme_port_offset = -100; } // LMS debug mode
var heci = require('heci');
this.INITIAL_RXWINDOW_SIZE = 4096;
this._LME = heci.create();
this._LME.LMS = this;
this._LME.on('error', function (e) { this.LMS.emit('error', e); });
this._LME.on('connect', function () {
this.LMS.emit('connect');
this.on('data', function (chunk) {
// this = HECI
var cmd = chunk.readUInt8(0);
//console.log('LME Command ' + cmd + ', ' + chunk.length + ' byte(s).');
switch (cmd) {
default:
console.log('Unhandled LME Command ' + cmd + ', ' + chunk.length + ' byte(s).');
break;
case APF_SERVICE_REQUEST:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5);
//console.log("Service Request for: " + name);
if (name == 'pfwd@amt.intel.com' || name == 'auth@amt.intel.com') {
var outBuffer = Buffer.alloc(5 + nameLen);
outBuffer.writeUInt8(6, 0);
outBuffer.writeUInt32BE(nameLen, 1);
outBuffer.write(name.toString(), 5);
this.write(outBuffer);
//console.log('Answering APF_SERVICE_REQUEST');
} else {
//console.log('UNKNOWN APF_SERVICE_REQUEST');
}
break;
case APF_GLOBAL_REQUEST:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5).toString();
switch (name) {
case 'tcpip-forward':
var len = chunk.readUInt32BE(nameLen + 6);
var port = chunk.readUInt32BE(nameLen + 10 + len);
//console.log("[" + chunk.length + "/" + len + "] APF_GLOBAL_REQUEST for: " + name + " on port " + port);
if (this[name] == undefined) { this[name] = {}; }
if (this[name][port] != null) { // Close the existing binding
for (var i in this.sockets) {
var channel = this.sockets[i];
if (channel.localPort == port) { this.sockets[i].end(); delete this.sockets[i]; } // Close this socket
}
}
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;
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 - lme_port_offset);
});
}
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(81, 0);
outBuffer.writeUInt32BE(port, 1);
this.write(outBuffer);
break;
case 'cancel-tcpip-forward':
var outBuffer = Buffer.alloc(1);
outBuffer.writeUInt8(APF_REQUEST_SUCCESS, 0);
this.write(outBuffer);
break;
case 'udp-send-to@amt.intel.com':
var outBuffer = Buffer.alloc(1);
outBuffer.writeUInt8(APF_REQUEST_FAILURE, 0);
this.write(outBuffer);
break;
default:
//console.log("Unknown APF_GLOBAL_REQUEST for: " + name);
break;
}
break;
case APF_CHANNEL_OPEN_CONFIRMATION:
var rChannel = chunk.readUInt32BE(1);
var sChannel = chunk.readUInt32BE(5);
var wSize = chunk.readUInt32BE(9);
//console.log('rChannel/' + rChannel + ', sChannel/' + sChannel + ', wSize/' + wSize);
if (this.sockets[rChannel] != undefined) {
this.sockets[rChannel].lme.amtId = sChannel;
this.sockets[rChannel].lme.rxWindow = wSize;
this.sockets[rChannel].lme.txWindow = wSize;
this.sockets[rChannel].lme.LME_CHANNEL_STATUS = 'LME_CS_CONNECTED';
//console.log('LME_CS_CONNECTED');
this.sockets[rChannel].bufferedStream = new stream_bufferedWrite();
this.sockets[rChannel].bufferedStream.socket = this.sockets[rChannel];
this.sockets[rChannel].bufferedStream.on('readable', function () {
if (this.socket.lme.txWindow > 0) {
var buffer = this.read(this.socket.lme.txWindow);
var packet = Buffer.alloc(9 + buffer.length);
packet.writeUInt8(APF_CHANNEL_DATA, 0);
packet.writeUInt32BE(this.socket.lme.amtId, 1);
packet.writeUInt32BE(buffer.length, 5);
buffer.copy(packet, 9);
this.socket.lme.txWindow -= buffer.length;
this.socket.HECI.write(packet);
}
});
this.sockets[rChannel].bufferedStream.on('drain', function () {
this.socket.resume();
});
this.sockets[rChannel].on('data', function (chunk) {
if (!this.bufferedStream.write(chunk)) { this.pause(); }
});
this.sockets[rChannel].on('end', function () {
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
outBuffer.writeUInt32BE(this.lme.amtId, 1);
this.HECI.write(outBuffer);
});
this.sockets[rChannel].resume();
}
break;
case APF_PROTOCOLVERSION:
var major = chunk.readUInt32BE(1);
var minor = chunk.readUInt32BE(5);
var reason = chunk.readUInt32BE(9);
var outBuffer = Buffer.alloc(93);
outBuffer.writeUInt8(192, 0);
outBuffer.writeUInt32BE(1, 1);
outBuffer.writeUInt32BE(0, 5);
outBuffer.writeUInt32BE(reason, 9);
//console.log('Answering PROTOCOL_VERSION');
this.write(outBuffer);
break;
case APF_CHANNEL_WINDOW_ADJUST:
var rChannelId = chunk.readUInt32BE(1);
var bytesToAdd = chunk.readUInt32BE(5);
if (this.sockets[rChannelId] != undefined) {
this.sockets[rChannelId].lme.txWindow += bytesToAdd;
if (!this.sockets[rChannelId].bufferedStream.isEmpty() && this.sockets[rChannelId].bufferedStream.isWaiting()) {
this.sockets[rChannelId].bufferedStream.emit('readable');
}
} else {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
}
break;
case APF_CHANNEL_DATA:
var rChannelId = chunk.readUInt32BE(1);
var dataLen = chunk.readUInt32BE(5);
var data = chunk.slice(9, 9 + dataLen);
if (this.sockets[rChannelId] != undefined) {
this.sockets[rChannelId].pendingBytes.push(data.length);
this.sockets[rChannelId].write(data, function () {
var written = this.pendingBytes.shift();
//console.log('adjust', this.lme.amtId, written);
var outBuffer = Buffer.alloc(9);
outBuffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
outBuffer.writeUInt32BE(this.lme.amtId, 1);
outBuffer.writeUInt32BE(written, 5);
this.HECI.write(outBuffer);
});
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
var channel = this.insockets[rChannelId];
if (channel.data == null) { channel.data = data.toString(); } else { channel.data += data.toString(); }
channel.rxWindow += dataLen;
//console.log('IN DATA', channel.rxWindow, channel.data.length, dataLen, channel.amtId, data.toString());
var httpData = parseHttp(channel.data);
if ((httpData != null) || (channel.data.length >= 8000)) {
// Event the http data
this.LMS.emit('notify', httpData, channel.options);
// Send channel close
var buffer = Buffer.alloc(5);
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
buffer.writeUInt32BE(amtId, 1);
this.write(buffer);
} else {
if (channel.rxWindow > 6000) {
// Send window adjust
var buffer = Buffer.alloc(9);
buffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
buffer.writeUInt32BE(channel.amtId, 1);
buffer.writeUInt32BE(channel.rxWindow, 5);
this.write(buffer);
channel.rxWindow = 0;
}
}
} else {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
}
break;
case APF_CHANNEL_CLOSE:
var rChannelId = chunk.readUInt32BE(1);
if (this.sockets[rChannelId] != undefined) {
this.sockets[rChannelId].end();
var amtId = this.sockets[rChannelId].lme.amtId;
var buffer = Buffer.alloc(5);
delete this.sockets[rChannelId];
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0); // ????????????????????????????
buffer.writeUInt32BE(amtId, 1);
this.write(buffer);
} else if ((this.insockets != null) && (this.insockets[rChannelId] != undefined)) {
delete this.insockets[rChannelId];
// Should I send a close back????
} else {
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_CLOSE');
}
break;
case APF_CHANNEL_OPEN:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5).toString();
var channelSender = chunk.readUInt32BE(nameLen + 5);
var initialWindowSize = chunk.readUInt32BE(nameLen + 9);
var hostToConnectLen = chunk.readUInt32BE(nameLen + 17);
var hostToConnect = chunk.slice(nameLen + 21, nameLen + 21 + hostToConnectLen).toString();
var portToConnect = chunk.readUInt32BE(nameLen + 21 + hostToConnectLen);
var originatorIpLen = chunk.readUInt32BE(nameLen + 25 + hostToConnectLen);
var originatorIp = chunk.slice(nameLen + 29 + hostToConnectLen, nameLen + 29 + hostToConnectLen + originatorIpLen).toString();
var originatorPort = chunk.readUInt32BE(nameLen + 29 + hostToConnectLen + originatorIpLen);
//console.log('APF_CHANNEL_OPEN', name, channelSender, initialWindowSize, 'From: ' + originatorIp + ':' + originatorPort, 'To: ' + hostToConnect + ':' + portToConnect);
if (this.insockets == null) { this.insockets = {}; }
var ourId = ++lme_id;
var insocket = new lme_object();
insocket.ourId = ourId;
insocket.amtId = channelSender;
insocket.txWindow = initialWindowSize;
insocket.rxWindow = 0;
insocket.options = { target: hostToConnect, targetPort: portToConnect, source: originatorIp, sourcePort: originatorPort };
this.insockets[ourId] = insocket;
var buffer = Buffer.alloc(17);
buffer.writeUInt8(APF_CHANNEL_OPEN_CONFIRMATION, 0);
buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel
buffer.writeUInt32BE(ourId, 5); // Our receiver channel id
buffer.writeUInt32BE(4000, 9); // Initial Window Size
buffer.writeUInt32BE(0xFFFFFFFF, 13); // Reserved
this.write(buffer);
/*
var buffer = Buffer.alloc(17);
buffer.writeUInt8(APF_CHANNEL_OPEN_FAILURE, 0);
buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel
buffer.writeUInt32BE(2, 5); // Reason code
buffer.writeUInt32BE(0, 9); // Reserved
buffer.writeUInt32BE(0, 13); // Reserved
this.write(buffer);
console.log('Sent APF_CHANNEL_OPEN_FAILURE', channelSender);
*/
break;
}
});
});
this.bindDuplexStream = function (duplexStream, remoteFamily, localPort) {
var socket = duplexStream;
//console.log('New [' + remoteFamily + '] Virtual Connection/' + socket.localPort);
socket.pendingBytes = [];
socket.HECI = this._LME;
socket.LMS = this;
socket.lme = new lme_object();
socket.lme.Socket = socket;
socket.localPort = localPort;
var buffer = new MemoryStream();
buffer.writeUInt8(0x5A);
buffer.writeUInt32BE(15);
buffer.write('forwarded-tcpip');
buffer.writeUInt32BE(socket.lme.ourId);
buffer.writeUInt32BE(this.INITIAL_RXWINDOW_SIZE);
buffer.writeUInt32BE(0xFFFFFFFF);
for (var i = 0; i < 2; ++i) {
if (remoteFamily == 'IPv6') {
buffer.writeUInt32BE(3);
buffer.write('::1');
} else {
buffer.writeUInt32BE(9);
buffer.write('127.0.0.1');
}
buffer.writeUInt32BE(localPort);
}
this._LME.write(buffer.buffer);
if (this._LME.sockets == undefined) { this._LME.sockets = {}; }
this._LME.sockets[socket.lme.ourId] = socket;
socket.pause();
};
this._LME.connect(heci.GUIDS.LME, { noPipeline: 0 });
}
function parseHttp(httpData) {
var i = httpData.indexOf('\r\n\r\n');
if ((i == -1) || (httpData.length < (i + 2))) { return null; }
var headers = require('http-headers')(httpData.substring(0, i), true);
var contentLength = parseInt(headers['content-length']);
if (httpData.length >= contentLength + i + 4) { return httpData.substring(i + 4, i + 4 + contentLength); }
return null;
}
module.exports = lme_heci;

View File

@ -0,0 +1,297 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var Q = require('queue');
function amt_heci() {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci');
this._amt = heci.create();
this._amt.BiosVersionLen = 65;
this._amt.UnicodeStringLen = 20;
this._amt.rq = new Q();
this._amt.Parent = this;
this._amt.on('error', function (e) { this.Parent.emit('error', e); });
this._amt.on('connect', function () {
this.Parent.emit('connect');
this.on('data', function (chunk) {
//console.log("Received: " + chunk.length + " bytes");
var header = this.Parent.getCommand(chunk);
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
var user = this.rq.deQueue();
var params = user.optional;
var callback = user.func;
params.unshift(header);
callback.apply(this.Parent, params);
});
});
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
this.getCommand = function (chunk) {
var command = chunk.length == 0 ? (this._amt.rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
var ret = { IsResponse: (command & 0x800000) == 0x800000 ? true : false, Command: (command & 0x7FFFFF), Status: chunk.length != 0 ? chunk.readUInt32LE(12) : -1, Data: chunk.length != 0 ? chunk.slice(16) : null };
return (ret);
};
this.sendCommand = function () {
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
var args = [];
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
this._amt.rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args });
var header = Buffer.from('010100000000000000000000', 'hex');
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
this._amt.write(arguments[1] == null ? header : Buffer.concat([header, arguments[1]]));
}
this.getVersion = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
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) {
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));
}
opt.unshift(val);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getProvisioningState = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(17, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.state = header.Data.readUInt32LE(0);
if (result.state < 3) { result.stateStr = ["PRE", "IN", "POST"][result.state]; }
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getProvisioningMode = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(8, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.mode = header.Data.readUInt32LE(0);
if (result.mode < 4) { result.modeStr = ["NONE", "ENTERPRISE", "SMALL_BUSINESS", "REMOTE_ASSISTANCE"][result.mode]; }
result.legacy = header.Data.readUInt32LE(4) == 0 ? false : true;
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getEHBCState = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(132, null, function (header, fn, opt) {
if (header.Status == 0) {
opt.unshift({ EHBC: header.Data.readUInt32LE(0) != 0 });
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getControlMode = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(107, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.controlMode = header.Data.readUInt32LE(0);
if (result.controlMode < 3) { result.controlModeStr = ["NONE_RPAT", "CLIENT", "ADMIN", "REMOTE_ASSISTANCE"][result.controlMode]; }
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getMACAddresses = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(37, null, function (header, fn, opt) {
if (header.Status == 0) {
opt.unshift({ DedicatedMAC: header.Data.slice(0, 6).toString('hex:'), HostMAC: header.Data.slice(6, 12).toString('hex:') });
} else { opt.unshift({ DedicatedMAC: null, HostMAC: null }); }
fn.apply(this, opt);
}, callback, optional);
};
this.getDnsSuffix = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(54, null, function (header, fn, opt) {
if (header.Status == 0) {
var resultLen = header.Data.readUInt16LE(0);
if (resultLen > 0) { opt.unshift(header.Data.slice(2, 2 + resultLen).toString()); } else { opt.unshift(null); }
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getHashHandles = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x2C, null, function (header, fn, opt) {
var result = [];
if (header.Status == 0) {
var resultLen = header.Data.readUInt32LE(0);
for (var i = 0; i < resultLen; ++i) {
result.push(header.Data.readUInt32LE(4 + (4 * i)));
}
}
opt.unshift(result);
fn.apply(this, opt);
}, callback, optional);
};
this.getCertHashEntry = function (handle, callback) {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
var data = new Buffer(4);
data.writeUInt32LE(handle, 0);
this.sendCommand(0x2D, data, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.isDefault = header.Data.readUInt32LE(0);
result.isActive = header.Data.readUInt32LE(4);
result.hashAlgorithm = header.Data.readUInt8(72);
if (result.hashAlgorithm < 4) {
result.hashAlgorithmStr = ["MD5", "SHA1", "SHA256", "SHA512"][result.hashAlgorithm];
result.hashAlgorithmSize = [16, 20, 32, 64][result.hashAlgorithm];
result.certificateHash = header.Data.slice(8, 8 + result.hashAlgorithmSize).toString('hex');
}
result.name = header.Data.slice(73 + 2, 73 + 2 + header.Data.readUInt16LE(73)).toString();
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getCertHashEntries = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.getHashHandles(function (handles, fn, opt) {
var entries = [];
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
}, callback, optional);
};
this._getHashEntrySink = function (result, fn, opt, entries, handles) {
entries.push(result);
if (handles.length > 0) {
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
} else {
opt.unshift(entries);
fn.apply(this, opt);
}
}
this.getLocalSystemAccount = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
if (header.Data.length == 68) { opt.unshift({ user: header.Data.slice(0, 34).toString(), pass: header.Data.slice(34, 67).toString(), raw: header.Data }); } else { opt.unshift(null); }
fn.apply(this, opt);
}, callback, optional);
}
this.unprovision = function (mode, callback) {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
var data = new Buffer(4);
data.writeUInt32LE(mode, 0);
this.sendCommand(16, data, function (header, fn, opt) {
opt.unshift(header.Status);
fn.apply(this, opt);
}, callback, optional);
}
this.startConfiguration = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x29, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.stopConfiguration = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x5E, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.openUserInitiatedConnection = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x44, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.closeUserInitiatedConnection = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x45, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.getRemoteAccessConnectionStatus = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x46, data, function (header, fn, opt) {
if (header.Status == 0) {
var hostname = v.slice(14, header.Data.readUInt16LE(12) + 14).toString()
opt.unshift({ status: header.Status, networkStatus: header.Data.readUInt32LE(0), remoteAccessStatus: header.Data.readUInt32LE(4), remoteAccessTrigger: header.Data.readUInt32LE(8), mpsHostname: hostname, raw: header.Data });
} else {
opt.unshift({ status: header.Status });
}
fn.apply(this, opt);
}, callback, optional);
}
this.getProtocolVersion = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
if (status == 0) {
var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
opt.unshift(result);
fn.apply(self, opt);
}
else {
opt.unshift(null);
fn.apply(self, opt);
}
}, this, callback, optional);
}
}
module.exports = amt_heci;

View File

@ -0,0 +1,456 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @fileoverview Script Compiler / Decompiler / Runner
* @author Ylian Saint-Hilaire
* @version v0.1.0e
*/
// Core functions
script_functionTable1 = ['nop', 'jump', 'set', 'print', 'dialog', 'getitem', 'substr', 'indexof', 'split', 'join', 'length', 'jsonparse', 'jsonstr', 'add', 'substract', 'parseint', 'wsbatchenum', 'wsput', 'wscreate', 'wsdelete', 'wsexec', 'scriptspeed', 'wssubscribe', 'wsunsubscribe', 'readchar', 'signwithdummyca'];
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
script_functionTable2 = ['encodeuri', 'decodeuri', 'passwordcheck', 'atob', 'btoa', 'hex2str', 'str2hex', 'random', 'md5', 'maketoarray', 'readshort', 'readshortx', 'readint', 'readsint', 'readintx', 'shorttostr', 'shorttostrx', 'inttostr', 'inttostrx'];
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
script_functionTableX2 = [encodeURI, decodeURI, passwordcheck, window.atob.bind(window), window.btoa.bind(window), hex2rstr, rstr2hex, random, rstr_md5, MakeToArray, ReadShort, ReadShortX, ReadInt, ReadSInt, ReadIntX, ShortToStr, ShortToStrX, IntToStr, IntToStrX];
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
script_functionTable3 = ['pullsystemstatus', 'pulleventlog', 'pullauditlog', 'pullcertificates', 'pullwatchdog', 'pullsystemdefense', 'pullhardware', 'pulluserinfo', 'pullremoteaccess', 'highlightblock', 'disconnect', 'getsidstring', 'getsidbytearray', 'pulleventsubscriptions'];
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
script_functionTableX3 = [
PullSystemStatus
,
// ###BEGIN###{EventLog}
PullEventLog
// ###END###{EventLog}
,
// ###BEGIN###{AuditLog}
PullAuditLog
// ###END###{AuditLog}
,
// ###BEGIN###{Certificates}
PullCertificates
// ###END###{Certificates}
,
// ###BEGIN###{AgentPresence}
PullWatchdog
// ###END###{AgentPresence}
,
// ###BEGIN###{SystemDefense}
PullSystemDefense
// ###END###{SystemDefense}
,
// ###BEGIN###{HardwareInfo}
PullHardware
// ###END###{HardwareInfo}
,
PullUserInfo
,
// ###BEGIN###{RemoteAccess}
PullRemoteAccess
// ###END###{RemoteAccess}
,
// ###BEGIN###{Scripting-Editor}
script_HighlightBlock
// ###END###{Scripting-Editor}
,
// ###BEGIN###{ComputerSelector}
disconnect
// ###END###{ComputerSelector}
,
function (runner, x) { return GetSidString(x); }
,
function (runner, x) { return GetSidByteArray(x); }
,
// ###BEGIN###{EventSubscriptions}
PullEventSubscriptions
// ###END###{EventSubscriptions}
];
// Setup the script state
function script_setup(binary, startvars) {
var obj = { startvars:startvars };
if (binary.length < 6) { console.error('Invalid script length'); return null; } // Script must have at least 6 byte header
if (ReadInt(binary, 0) != 0x247D2945) { console.error('Invalid binary script'); return null; } // Check the script magic header
if (ReadShort(binary, 4) > 1) { console.error('Unsupported script version'); return null; } // Check the script version
obj.script = binary.substring(6);
// obj.onStep;
// obj.onConsole;
// Reset the script to the start
obj.reset = function (stepspeed) {
obj.stop();
obj.ip = 0;
obj.variables = startvars;
obj.state = 1;
}
// Start the script
obj.start = function (stepspeed) {
obj.stop();
obj.stepspeed = stepspeed;
if (stepspeed > 0) { obj.timer = setInterval(function () { obj.step() }, stepspeed); }
}
// Stop the script
obj.stop = function () {
if (obj.timer != null) { clearInterval(obj.timer); }
obj.timer = null;
obj.stepspeed = 0;
}
// function used to load and store variable values
obj.getVar = function (name) { if (name == undefined) return undefined; return obj.getVarEx(name.split('.'), obj.variables); }
obj.getVarEx = function (name, val) { try { if (name == undefined) return undefined; if (name.length == 0) return val; return obj.getVarEx(name.slice(1), val[name[0]]); } catch (e) { return null; } }
obj.setVar = function (name, val) { obj.setVarEx(name.split('.'), obj.variables, val); }
obj.setVarEx = function (name, vars, val) { if (name.length == 1) { vars[name[0]] = val; } else { obj.setVarEx(name.slice(1), vars[name[0]], val); } }
// Run the script one step forward
obj.step = function () {
if (obj.state != 1) return;
if (obj.ip < obj.script.length) {
var cmdid = ReadShort(obj.script, obj.ip);
var cmdlen = ReadShort(obj.script, obj.ip + 2);
var argcount = ReadShort(obj.script, obj.ip + 4);
var argptr = obj.ip + 6;
var args = [];
// Clear all temp variables (This is optional)
for (var i in obj.variables) { if (i.startsWith('__')) { delete obj.variables[i]; } }
// Loop on each argument, moving forward by the argument length each time
for (var i = 0; i < argcount; i++) {
var arglen = ReadShort(obj.script, argptr);
var argval = obj.script.substring(argptr + 2, argptr + 2 + arglen);
var argtyp = argval.charCodeAt(0);
argval = argval.substring(1);
if (argtyp < 2) {
// Get the value and replace all {var} with variable values
while (argval.split("{").length > 1) { var t = argval.split("{").pop().split("}").shift(); argval = argval.replace('{' + t + '}', obj.getVar(t)); }
if (argtyp == 1) { obj.variables['__' + i] = decodeURI(argval); argval = '__' + i; } // If argtyp is 1, this is a literal. Store in temp variable.
args.push(argval);
}
if (argtyp == 2 || argtyp == 3) {
obj.variables['__' + i] = ReadSInt(argval, 0);
args.push('__' + i);
}
argptr += (2 + arglen);
}
// Move instruction pointer forward by command size
obj.ip += cmdlen;
// Get all variable values
var argsval = [];
for (var i = 0; i < 10; i++) { argsval.push(obj.getVar(args[i])); }
var storeInArg0;
try {
if (cmdid < 10000) {
// Lets run the actual command
switch (cmdid) {
case 0: // nop
break;
case 1: // jump(label) or jump(label, a, compare, b)
if (argsval[2]) {
if (
(argsval[2] == '<' && argsval[1] < argsval[3]) ||
(argsval[2] == '<=' && argsval[1] <= argsval[3]) ||
(argsval[2] == '!=' && argsval[1] != argsval[3]) ||
(argsval[2] == '=' && argsval[1] == argsval[3]) ||
(argsval[2] == '>=' && argsval[1] >= argsval[3]) ||
(argsval[2] == '>' && argsval[1] > argsval[3])
) { obj.ip = argsval[0]; }
} else {
obj.ip = argsval[0]; // Set the instruction pointer to the new location in the script
}
break;
case 2: // set(variable, value)
if (args[1] == undefined) delete obj.variables[args[0]]; else obj.setVar(args[0], argsval[1]);
break;
case 3: // print(message)
if (obj.onConsole) { obj.onConsole(obj.toString(argsval[0]), obj); } else { console.log(obj.toString(argsval[0])); }
// Q(obj.consoleid).value += () + '\n'); Q(obj.console).scrollTop = Q(obj.console).scrollHeight;
break;
case 4: // dialog(title, content, buttons)
obj.state = 2;
obj.dialog = true;
setDialogMode(11, argsval[0], argsval[2], obj.xxStepDialogOk, argsval[1], obj);
break;
case 5: // getitem(a, b, c)
for (var i in argsval[1]) { if (argsval[1][i][argsval[2]] == argsval[3]) { storeInArg0 = i; } };
break;
case 6: // substr(variable_dest, variable_src, index, len)
storeInArg0 = argsval[1].substr(argsval[2], argsval[3]);
break;
case 7: // indexOf(variable_dest, variable_src, index, len)
storeInArg0 = argsval[1].indexOf(argsval[2]);
break;
case 8: // split(variable_dest, variable_src, separator)
storeInArg0 = argsval[1].split(argsval[2]);
break;
case 9: // join(variable_dest, variable_src, separator)
storeInArg0 = argsval[1].join(argsval[2]);
break;
case 10: // length(variable_dest, variable_src)
storeInArg0 = argsval[1].length;
break;
case 11: // jsonparse(variable_dest, json)
storeInArg0 = JSON.parse(argsval[1]);
break;
case 12: // jsonstr(variable_dest, variable_src)
storeInArg0 = JSON.stringify(argsval[1]);
break;
case 13: // add(variable_dest, variable_src, value)
storeInArg0 = (argsval[1] + argsval[2]);
break;
case 14: // substract(variable_dest, variable_src, value)
storeInArg0 = (argsval[1] - argsval[2]);
break;
case 15: // parseInt(variable_dest, variable_src)
storeInArg0 = parseInt(argsval[1]);
break;
case 16: // wsbatchenum(name, objectList)
obj.state = 2;
obj.amtstack.BatchEnum(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
break;
case 17: // wsput(name, args)
obj.state = 2;
obj.amtstack.Put(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
break;
case 18: // wscreate(name, args)
obj.state = 2;
obj.amtstack.Create(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
break;
case 19: // wsdelete(name, args)
obj.state = 2;
obj.amtstack.Delete(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
break;
case 20: // wsexec(name, method, args, selectors)
obj.state = 2;
obj.amtstack.Exec(argsval[0], argsval[1], argsval[2], obj.xxWsmanReturn, obj, 0, argsval[3]);
break;
case 21: // Script Speed
obj.stepspeed = argsval[0];
if (obj.timer != null) { clearInterval(obj.timer); obj.timer = setInterval(function () { obj.step() }, obj.stepspeed); }
break;
case 22: // wssubscribe(name, delivery, url, selectors, opaque, user, pass)
obj.state = 2;
obj.amtstack.Subscribe(argsval[0], argsval[1], argsval[2], obj.xxWsmanReturn, obj, 0, argsval[3], argsval[4], argsval[5], argsval[6]);
break;
case 23: // wsunsubscribe(name, selectors)
obj.state = 2;
obj.amtstack.UnSubscribe(argsval[0], obj.xxWsmanReturn, obj, 0, argsval[1]);
break;
case 24: // readchar(str, pos)
console.log(argsval[1], argsval[2], argsval[1].charCodeAt(argsval[2]));
storeInArg0 = argsval[1].charCodeAt(argsval[2]);
break;
case 25: // signWithDummyCa
// ###BEGIN###{Certificates}
obj.state = 2;
// DERKey, xxCaPrivateKey, certattributes, issuerattributes
amtcert_signWithCaKey(argsval[0], null, argsval[1], { 'CN': 'Untrusted Root Certificate' }, obj.xxSignWithDummyCaReturn);
// ###END###{Certificates}
break;
default: {
obj.state = 9;
console.error("Script Error, unknown command: " + cmdid);
}
}
} else {
if (cmdid < 20000) {
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
storeInArg0 = script_functionTableX2[cmdid - 10000](argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]);
} else {
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
if (script_functionTableX3 && script_functionTableX3[cmdid - 20000]) {
storeInArg0 = script_functionTableX3[cmdid - 20000](obj, argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]); // Note that optional calls start with "obj" as first argument.
}
}
}
if (storeInArg0 != undefined) obj.setVar(args[0], storeInArg0);
} catch (e) {
if (typeof e == 'object') { e = e.message; }
obj.setVar('_exception', e);
}
}
if (obj.state == 1 && obj.ip >= obj.script.length) { obj.state = 0; obj.stop(); }
if (obj.onStep) obj.onStep(obj);
return obj;
}
obj.xxStepDialogOk = function (button) {
obj.variables['DialogSelect'] = button;
obj.state = 1;
obj.dialog = false;
if (obj.onStep) obj.onStep(obj);
}
// ###BEGIN###{**ClosureAdvancedMode}
obj.xxWsmanReturnFix = function (x) {
if (!x || x == null) return;
if (x.Header) { x['Header'] = x.Header; delete x.Header; }
if (x.Body) { x['Body'] = x.Body; delete x.Body; }
if (x.Responses) { x['Responses'] = x.Responses; delete x.Responses; }
if (x.Response) { x['Response'] = x.Response; delete x.Response; }
if (x.ReturnValueStr) { x['ReturnValueStr'] = x.ReturnValueStr; delete x.ReturnValueStr; }
}
// ###END###{**ClosureAdvancedMode}
obj.xxWsmanReturn = function (stack, name, responses, status) {
// ###BEGIN###{**ClosureAdvancedMode}
// This is required when Google Closure is used
if (responses) {
obj.xxWsmanReturnFix(responses);
for (var i in responses) {
obj.xxWsmanReturnFix(responses[i]);
for (var j in responses[i]) { obj.xxWsmanReturnFix(responses[i][j]); }
}
}
// ###END###{**ClosureAdvancedMode}
obj.setVar(name, responses);
obj.setVar('wsman_result', status);
obj.setVar('wsman_result_str', ((httpErrorTable[status]) ? (httpErrorTable[status]) : ('Error #' + status)));
obj.state = 1;
if (obj.onStep) obj.onStep(obj);
}
// ###BEGIN###{Certificates}
obj.xxSignWithDummyCaReturn = function (cert) {
obj.setVar('signed_cert', btoa(_arrayBufferToString(cert)));
obj.state = 1;
if (obj.onStep) obj.onStep(obj);
}
// ###END###{Certificates}
obj.toString = function (x) { if (typeof x == 'object') return JSON.stringify(x); return x; }
obj.reset();
return obj;
}
// Argument types: 0 = Variable, 1 = String, 2 = Integer, 3 = Label
function script_compile(script, onmsg) {
var r = '', scriptlines = script.split('\n'), labels = {}, labelswap = [], swaps = [];
// Go thru each script line and encode it
for (var i in scriptlines) {
var scriptline = scriptlines[i];
if (scriptline.startsWith('##SWAP ')) { var x = scriptline.split(' '); if (x.length == 3) { swaps[x[1]] = x[2]; } } // Add a swap instance
if (scriptline[0] == '#' || scriptline.length == 0) continue; // Skip comments & blank lines
for (var x in swaps) { scriptline = scriptline.split(x).join(swaps[x]); } // Apply all swaps
var keywords = scriptline.match(/"[^"]*"|[^\s"]+/g);
if (keywords.length == 0) continue; // Skip blank lines
if (scriptline[0] == ':') { labels[keywords[0].toUpperCase()] = r.length; continue; } // Mark a label position
var funcIndex = script_functionTable1.indexOf(keywords[0].toLowerCase());
if (funcIndex == -1) { funcIndex = script_functionTable2.indexOf(keywords[0].toLowerCase()); if (funcIndex >= 0) funcIndex += 10000; }
if (funcIndex == -1) { funcIndex = script_functionTable3.indexOf(keywords[0].toLowerCase()); if (funcIndex >= 0) funcIndex += 20000; } // Optional methods
if (funcIndex == -1) { if (onmsg) { onmsg("Unabled to compile, unknown command: " + keywords[0]); } return ''; }
// Encode CommandId, CmdSize, ArgCount, Arg1Len, Arg1, Arg2Len, Arg2...
var cmd = ShortToStr(keywords.length - 1);
for (var j in keywords) {
if (j == 0) continue;
if (keywords[j][0] == ':') {
labelswap.push([keywords[j], r.length + cmd.length + 7]); // Add a label swap
cmd += ShortToStr(5) + String.fromCharCode(3) + IntToStr(0xFFFFFFFF); // Put an empty label
} else {
var argint = parseInt(keywords[j]);
if (argint == keywords[j]) {
cmd += ShortToStr(5) + String.fromCharCode(2) + IntToStr(argint);
} else {
if (keywords[j][0] == '"' && keywords[j][keywords[j].length - 1] == '"') {
cmd += ShortToStr(keywords[j].length - 1) + String.fromCharCode(1) + keywords[j].substring(1, keywords[j].length - 1);
} else {
cmd += ShortToStr(keywords[j].length + 1) + String.fromCharCode(0) + keywords[j];
}
}
}
}
cmd = ShortToStr(funcIndex) + ShortToStr(cmd.length + 4) + cmd;
r += cmd;
}
// Perform all the needed label swaps
for (i in labelswap) {
var label = labelswap[i][0].toUpperCase(), position = labelswap[i][1], target = labels[label];
if (target == undefined) { if (onmsg) { onmsg("Unabled to compile, unknown label: " + label); } return ''; }
r = r.substr(0, position) + IntToStr(target) + r.substr(position + 4);
}
return IntToStr(0x247D2945) + ShortToStr(1) + r;
}
// Decompile the script, intended for debugging only
function script_decompile(binary, onecmd) {
var r = '', ptr = 6, labelcount = 0, labels = {};
if (onecmd >= 0) {
ptr = onecmd; // If we are decompiling just one command, set the ptr to that command.
} else {
if (binary.length < 6) { return '# Invalid script length'; }
var magic = ReadInt(binary, 0);
var version = ReadShort(binary, 4);
if (magic != 0x247D2945) { return '# Invalid binary script: ' + magic; }
if (version != 1) { return '# Invalid script version'; }
}
// Loop on each command, moving forward by the command length each time.
while (ptr < binary.length) {
var cmdid = ReadShort(binary, ptr);
var cmdlen = ReadShort(binary, ptr + 2);
var argcount = ReadShort(binary, ptr + 4);
var argptr = ptr + 6;
var argstr = '';
if (!(onecmd >= 0)) r += ":label" + (ptr - 6) + "\n";
// Loop on each argument, moving forward by the argument length each time
for (var i = 0; i < argcount; i++) {
var arglen = ReadShort(binary, argptr);
var argval = binary.substring(argptr + 2, argptr + 2 + arglen);
var argtyp = argval.charCodeAt(0);
if (argtyp == 0) { argstr += ' ' + argval.substring(1); } // Variable
else if (argtyp == 1) { argstr += ' \"' + argval.substring(1) + '\"'; } // String
else if (argtyp == 2) { argstr += ' ' + ReadInt(argval, 1); } // Integer
else if (argtyp == 3) { // Label
var target = ReadInt(argval, 1);
var label = labels[target];
if (!label) { label = ":label" + target; labels[label] = target; }
argstr += ' ' + label;
}
argptr += (2 + arglen);
}
// Go in the script function table to decode the function
if (cmdid < 10000) {
r += script_functionTable1[cmdid] + argstr + "\n";
} else {
if (cmdid >= 20000) {
r += script_functionTable3[cmdid - 20000] + argstr + "\n"; // Optional methods
} else {
r += script_functionTable2[cmdid - 10000] + argstr + "\n";
}
}
ptr += cmdlen;
if (onecmd >= 0) return r; // If we are decompiling just one command, exit now
}
// Remove all unused labels
var scriptlines = r.split('\n');
r = '';
for (var i in scriptlines) {
var line = scriptlines[i];
if (line[0] != ':') { r += line + '\n'; } else { if (labels[line]) { r += line + '\n'; } }
}
return r;
}

View File

@ -0,0 +1,121 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @description WSMAN communication using duktape http
* @author Ylian Saint-Hilaire
* @version v0.2.0c
*/
// Construct a WSMAN communication object
function CreateWsmanComm(host, port, user, pass, tls, extra) {
var obj = {};
obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start.
obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls
obj.MaxActiveAjaxCount = 1; // Maximum number of activate AJAX calls at the same time.
obj.FailAllError = 0; // Set this to non-zero to fail all AJAX calls with that error status, 999 causes responses to be silent.
obj.host = host;
obj.port = port;
obj.user = user;
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.
obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
if ((obj.ActiveAjaxCount == 0 || ((obj.ActiveAjaxCount < obj.MaxActiveAjaxCount) && (obj.challengeParams != null))) && obj.PendingAjax.length == 0) {
// There are no pending AJAX calls, perform the call now.
obj.PerformAjaxEx(postdata, callback, tag, url, action);
} else {
// If this is a high priority call, put this call in front of the array, otherwise put it in the back.
if (pri == 1) { obj.PendingAjax.unshift([postdata, callback, tag, url, action]); } else { obj.PendingAjax.push([postdata, callback, tag, url, action]); }
}
}
// Private method
obj.PerformNextAjax = function () {
if (obj.ActiveAjaxCount >= obj.MaxActiveAjaxCount || obj.PendingAjax.length == 0) return;
var x = obj.PendingAjax.shift();
obj.PerformAjaxEx(x[0], x[1], x[2], x[3], x[4]);
obj.PerformNextAjax();
}
// Private method
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
// 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, 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]);
} else {
response.acc = '';
response.on('data', function (data2) { this.acc += data2; });
response.on('end', function () { obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); });
}
});
// Send POST body, this work with binary.
req.write(postdata);
req.end();
obj.ActiveAjaxCount++;
return req;
}
// AJAX specific private method
obj.pendingAjaxCall = [];
// Private method
obj.gotNextMessages = function (data, status, request, callArgs) {
obj.ActiveAjaxCount--;
if (obj.FailAllError == 999) return;
//console.log("RECV: " + data); // DEBUG
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
if (request.status != 200) { callArgs[1](null, request.status, callArgs[2]); return; }
callArgs[1](data, 200, callArgs[2]);
obj.PerformNextAjax();
}
// Private method
obj.gotNextMessagesError = function (request, status, errorThrown, callArgs) {
obj.ActiveAjaxCount--;
if (obj.FailAllError == 999) return;
if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
//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();
}
// Cancel all pending queries with given status
obj.CancelAllQueries = function (s) {
while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
}
return obj;
}
module.exports = CreateWsmanComm;

View File

@ -0,0 +1,332 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @description Intel(r) AMT WSMAN Stack
* @author Ylian Saint-Hilaire
* @version v0.2.0
*/
// Construct a MeshServer object
function WsmanStackCreateService(CreateWsmanComm, host, port, user, pass, tls, extra) {
var obj = {};
//obj.onDebugMessage = null; // Set to a function if you want to get debug messages.
obj.NextMessageId = 1; // Next message number, used to label WSMAN calls.
obj.Address = '/wsman';
obj.comm = new CreateWsmanComm(host, port, user, pass, tls, extra);
obj.PerformAjax = function (postdata, callback, tag, pri, namespaces) {
if (namespaces == null) namespaces = '';
obj.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns=\"http://www.w3.org/2003/05/soap-envelope\" ' + namespaces + '><Header><a:Action>' + postdata, function (data, status, tag) {
if (status != 200) { callback(obj, null, { Header: { HttpError: status } }, status, tag); return; }
var wsresponse = obj.ParseWsman(data);
if (!wsresponse || wsresponse == null) { callback(obj, null, { Header: { HttpError: status } }, 601, tag); } else { callback(obj, wsresponse.Header["ResourceURI"], wsresponse, 200, tag); }
}, tag, pri);
}
// Private method
//obj.Debug = function (msg) { /*console.log(msg);*/ }
// Cancel all pending queries with given status
obj.CancelAllQueries = function (s) { obj.comm.CancelAllQueries(s); }
// Get the last element of a URI string
obj.GetNameFromUrl = function (resuri) {
var x = resuri.lastIndexOf("/");
return (x == -1)?resuri:resuri.substring(x + 1);
}
// Perform a WSMAN Subscribe operation
obj.ExecSubscribe = function (resuri, delivery, url, callback, tag, pri, selectors, opaque, user, pass) {
var digest = "", digest2 = "", opaque = "";
if (user != null && pass != null) { digest = '<t:IssuedTokens xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>' + user + '</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">' + pass + '</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>'; digest2 = '<w:Auth Profile="http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/http/digest"/>'; }
if (opaque != null) { opaque = '<a:ReferenceParameters><m:arg>' + opaque + '</m:arg></a:ReferenceParameters>'; }
if (delivery == 'PushWithAck') { delivery = 'dmtf.org/wbem/wsman/1/wsman/PushWithAck'; } else if (delivery == 'Push') { delivery = 'xmlsoap.org/ws/2004/08/eventing/DeliveryModes/Push'; }
var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>" + _PutObjToSelectorsXml(selectors) + digest + '</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.' + delivery + '"><e:NotifyTo><a:Address>' + url + '</a:Address>' + opaque + '</e:NotifyTo>' + digest2 + '</e:Delivery></e:Subscribe>';
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:m="http://x.com"');
}
// Perform a WSMAN UnSubscribe operation
obj.ExecUnSubscribe = function (resuri, callback, tag, pri, selectors) {
var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>" + _PutObjToSelectorsXml(selectors) + '</Header><Body><e:Unsubscribe/>';
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"');
}
// Perform a WSMAN PUT operation
obj.ExecPut = function (resuri, putobj, callback, tag, pri, selectors) {
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + '</Header><Body>' + _PutObjToBodyXml(resuri, putobj);
obj.PerformAjax(data + "</Body></Envelope>", callback, tag, pri);
}
// Perform a WSMAN CREATE operation
obj.ExecCreate = function (resuri, putobj, callback, tag, pri, selectors) {
var objname = obj.GetNameFromUrl(resuri);
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + "</Header><Body><g:" + objname + " xmlns:g=\"" + resuri + "\">";
for (var n in putobj) { data += "<g:" + n + ">" + putobj[n] + "</g:" + n + ">" }
obj.PerformAjax(data + "</g:" + objname + "></Body></Envelope>", callback, tag, pri);
}
// Perform a WSMAN DELETE operation
obj.ExecDelete = function (resuri, putobj, callback, tag, pri) {
var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(putobj) + "</Header><Body /></Envelope>";
obj.PerformAjax(data, callback, tag, pri);
}
// Perform a WSMAN GET operation
obj.ExecGet = function (resuri, callback, tag, pri) {
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>", callback, tag, pri);
}
// Perform a WSMAN method call operation
obj.ExecMethod = function (resuri, method, args, callback, tag, pri, selectors) {
var argsxml = "";
for (var i in args) { if (args[i] != null) { if (Array.isArray(args[i])) { for (var x in args[i]) { argsxml += "<r:" + i + ">" + args[i][x] + "</r:" + i + ">"; } } else { argsxml += "<r:" + i + ">" + args[i] + "</r:" + i + ">"; } } }
obj.ExecMethodXml(resuri, method, argsxml, callback, tag, pri, selectors);
}
// Perform a WSMAN method call operation. The arguments are already formatted in XML.
obj.ExecMethodXml = function (resuri, method, argsxml, callback, tag, pri, selectors) {
obj.PerformAjax(resuri + "/" + method + "</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>" + _PutObjToSelectorsXml(selectors) + "</Header><Body><r:" + method + '_INPUT' + " xmlns:r=\"" + resuri + "\">" + argsxml + "</r:" + method + "_INPUT></Body></Envelope>", callback, tag, pri);
}
// Perform a WSMAN ENUM operation
obj.ExecEnum = function (resuri, callback, tag, pri) {
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\" /></Body></Envelope>", callback, tag, pri);
}
// Perform a WSMAN PULL operation
obj.ExecPull = function (resuri, enumctx, callback, tag, pri) {
obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>" + obj.Address + "</a:To><w:ResourceURI>" + resuri + "</w:ResourceURI><a:MessageID>" + (obj.NextMessageId++) + "</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\"><EnumerationContext>" + enumctx + "</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>", callback, tag, pri);
}
// Private method
obj.ParseWsman = function (xml) {
try {
if (!xml.childNodes) xml = _turnToXml(xml);
var r = { Header:{} }, header = xml.getElementsByTagName("Header")[0], t;
if (!header) header = xml.getElementsByTagName("a:Header")[0];
if (!header) return null;
for (var i = 0; i < header.childNodes.length; i++) {
var child = header.childNodes[i];
r.Header[child.localName] = child.textContent;
}
var body = xml.getElementsByTagName("Body")[0];
if (!body) body = xml.getElementsByTagName("a:Body")[0];
if (!body) return null;
if (body.childNodes.length > 0) {
t = body.childNodes[0].localName;
if (t.indexOf("_OUTPUT") == t.length - 7) { t = t.substring(0, t.length - 7); }
r.Header['Method'] = t;
r.Body = _ParseWsmanRec(body.childNodes[0]);
}
return r;
} catch (e) {
console.log("Unable to parse XML: " + xml);
return null;
}
}
// Private method
function _ParseWsmanRec(node) {
var data, r = {};
for (var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
if ((child.childElementCount == null) || (child.childElementCount == 0)) { data = child.textContent; } else { data = _ParseWsmanRec(child); }
if (data == 'true') data = true; // Convert 'true' into true
if (data == 'false') data = false; // Convert 'false' into false
if ((parseInt(data) + '') === data) data = parseInt(data); // Convert integers
var childObj = data;
if ((child.attributes != null) && (child.attributes.length > 0)) {
childObj = { 'Value': data };
for(var j = 0; j < child.attributes.length; j++) {
childObj['@' + child.attributes[j].name] = child.attributes[j].value;
}
}
if (r[child.localName] instanceof Array) { r[child.localName].push(childObj); }
else if (r[child.localName] == null) { r[child.localName] = childObj; }
else { r[child.localName] = [r[child.localName], childObj]; }
}
return r;
}
function _PutObjToBodyXml(resuri, putObj) {
if (!resuri || putObj == null) return '';
var objname = obj.GetNameFromUrl(resuri);
var result = '<r:' + objname + ' xmlns:r="' + resuri + '">';
for (var prop in putObj) {
if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue;
if (putObj[prop] == null || typeof putObj[prop] === 'function') continue;
if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) {
result += '<r:' + prop + '><a:Address>' + putObj[prop].Address + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + putObj[prop]['ReferenceParameters']["ResourceURI"] + '</w:ResourceURI><w:SelectorSet>';
var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector'];
if (Array.isArray(selectorArray)) {
for (var i=0; i< selectorArray.length; i++) {
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
}
}
else {
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
}
result += '</w:SelectorSet></a:ReferenceParameters></r:' + prop + '>';
}
else {
if (Array.isArray(putObj[prop])) {
for (var i = 0; i < putObj[prop].length; i++) {
result += '<r:' + prop + '>' + putObj[prop][i].toString() + '</r:' + prop + '>';
}
} else {
result += '<r:' + prop + '>' + putObj[prop].toString() + '</r:' + prop + '>';
}
}
}
result += '</r:' + objname + '>';
return result;
}
/*
convert
{ @Name: 'InstanceID', @AttrName: 'Attribute Value'}
into
' Name="InstanceID" AttrName="Attribute Value" '
*/
function _ObjectToXmlAttributes(objWithAttributes) {
if(!objWithAttributes) return '';
var result = ' ';
for (var propName in objWithAttributes) {
if (!objWithAttributes.hasOwnProperty(propName) || propName.indexOf('@') !== 0) continue;
result += propName.substring(1) + '="' + objWithAttributes[propName] + '" ';
}
return result;
}
function _PutObjToSelectorsXml(selectorSet) {
if (!selectorSet) return '';
if (typeof selectorSet == 'string') return selectorSet;
if (selectorSet['InstanceID']) return "<w:SelectorSet><w:Selector Name=\"InstanceID\">" + selectorSet['InstanceID'] + "</w:Selector></w:SelectorSet>";
var result = '<w:SelectorSet>';
for(var propName in selectorSet) {
if (!selectorSet.hasOwnProperty(propName)) continue;
result += '<w:Selector Name="' + propName + '">';
if (selectorSet[propName]['ReferenceParameters']) {
result += '<a:EndpointReference>';
result += '<a:Address>' + selectorSet[propName]['Address'] + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + selectorSet[propName]['ReferenceParameters']['ResourceURI'] + '</w:ResourceURI><w:SelectorSet>';
var selectorArray = selectorSet[propName]['ReferenceParameters']['SelectorSet']['Selector'];
if (Array.isArray(selectorArray)) {
for (var i = 0; i < selectorArray.length; i++) {
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>';
}
}
else {
result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>';
}
result += '</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>';
} else {
result += selectorSet[propName];
}
result += '</w:Selector>';
}
result += '</w:SelectorSet>';
return result;
}
// This is a drop-in replacement to _turnToXml() that works without xml parser dependency.
Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : null); } });
function _treeBuilder() {
this.tree = [];
this.push = function (element) { this.tree.push(element); };
this.pop = function () { var element = this.tree.pop(); if (this.tree.length > 0) { var x = this.tree.peek(); x.childNodes.push(element); x.childElementCount = x.childNodes.length; } return (element); };
this.peek = function () { return (this.tree.peek()); }
this.addNamespace = function (prefix, namespace) { this.tree.peek().nsTable[prefix] = namespace; if (this.tree.peek().attributes.length > 0) { for (var i = 0; i < this.tree.peek().attributes; ++i) { var a = this.tree.peek().attributes[i]; if (prefix == '*' && a.name == a.localName) { a.namespace = namespace; } else if (prefix != '*' && a.name != a.localName) { var pfx = a.name.split(':')[0]; if (pfx == prefix) { a.namespace = namespace; } } } } }
this.getNamespace = function (prefix) { for (var i = this.tree.length - 1; i >= 0; --i) { if (this.tree[i].nsTable[prefix] != null) { return (this.tree[i].nsTable[prefix]); } } return null; }
}
function _turnToXml(text) { if (text == null) return null; return ({ childNodes: [_turnToXmlRec(text)], getElementsByTagName: _getElementsByTagName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS }); }
function _getElementsByTagNameNS(ns, name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name && (node.namespace == ns || ns == '*')) { ret.push(node); } }); return ret; }
function _getElementsByTagName(name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name) { ret.push(node); } }); return ret; }
function _getChildElementsByTagName(name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name) { ret.push(this.childNodes[node]); } } } return (ret); }
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) {
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]); }
}
var x = { name: attrName, value: attrValue }
if (attrNS != null) x.namespace = attrNS;
elementStack.peek().attributes.push(x);
}
}
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(); }
}
}
return lastElement;
}
return obj;
}
module.exports = WsmanStackCreateService;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,324 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
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;
var APF_SERVICE_REQUEST = 5;
var APF_SERVICE_ACCEPT = 6;
var APF_USERAUTH_REQUEST = 50;
var APF_USERAUTH_FAILURE = 51;
var APF_USERAUTH_SUCCESS = 52;
var APF_GLOBAL_REQUEST = 80;
var APF_REQUEST_SUCCESS = 81;
var APF_REQUEST_FAILURE = 82;
var APF_CHANNEL_OPEN = 90;
var APF_CHANNEL_OPEN_CONFIRMATION = 91;
var APF_CHANNEL_OPEN_FAILURE = 92;
var APF_CHANNEL_WINDOW_ADJUST = 93;
var APF_CHANNEL_DATA = 94;
var APF_CHANNEL_CLOSE = 97;
var APF_PROTOCOLVERSION = 192;
function lme_object() {
this.ourId = ++lme_id;
this.amtId = -1;
this.LME_CHANNEL_STATUS = 'LME_CS_FREE';
this.txWindow = 0;
this.rxWindow = 0;
this.localPort = 0;
this.errorCount = 0;
}
function stream_bufferedWrite() {
var emitterUtils = require('events').inherits(this);
this.buffer = [];
this._readCheckImmediate = undefined;
// Writable Events
emitterUtils.createEvent('close');
emitterUtils.createEvent('drain');
emitterUtils.createEvent('error');
emitterUtils.createEvent('finish');
emitterUtils.createEvent('pipe');
emitterUtils.createEvent('unpipe');
// Readable Events
emitterUtils.createEvent('readable');
this.isEmpty = function () {
return (this.buffer.length == 0);
};
this.isWaiting = function () {
return (this._readCheckImmediate == undefined);
};
this.write = function (chunk) {
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 });
this.emit('readable');
return (this.buffer.length == 0 ? true : false);
};
this.read = function () {
var size = arguments.length == 0 ? undefined : arguments[0];
var bytesRead = 0;
var list = [];
while ((size == undefined || bytesRead < size) && this.buffer.length > 0) {
var len = this.buffer[0].data.length - this.buffer[0].offset;
var offset = this.buffer[0].offset;
if (len > (size - bytesRead)) {
// Only reading a subset
list.push(this.buffer[0].data.slice(offset, offset + size - bytesRead));
this.buffer[0].offset += (size - bytesRead);
bytesRead += (size - bytesRead);
} else {
// Reading the entire thing
list.push(this.buffer[0].data.slice(offset));
bytesRead += len;
this.buffer.shift();
}
}
this._readCheckImmediate = setImmediate(function (buffered) {
buffered._readCheckImmediate = undefined;
if (buffered.buffer.length == 0) {
buffered.emit('drain'); // Drained
} else {
buffered.emit('readable'); // Not drained
}
}, this);
return (Buffer.concat(list));
};
}
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;
this._LME = heci.create();
this._LME.LMS = this;
this._LME.on('error', function (e) { this.LMS.emit('error', e); });
this._LME.on('connect', function () {
this.LMS.emit('connect');
this.on('data', function (chunk) {
// this = HECI
var cmd = chunk.readUInt8(0);
switch (cmd) {
default:
//console.log('Received ' + chunk.length + ' bytes of data for LMS');
//console.log('Command = ' + cmd);
break;
case APF_SERVICE_REQUEST:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5);
//console.log("Service Request for: " + name);
if (name == 'pfwd@amt.intel.com' || name == 'auth@amt.intel.com') {
var outBuffer = Buffer.alloc(5 + nameLen);
outBuffer.writeUInt8(6, 0);
outBuffer.writeUInt32BE(nameLen, 1);
outBuffer.write(name.toString(), 5);
this.write(outBuffer);
//console.log('Answering APF_SERVICE_REQUEST');
} else {
//console.log('UNKNOWN APF_SERVICE_REQUEST');
}
break;
case APF_GLOBAL_REQUEST:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5).toString();
switch (name) {
case 'tcpip-forward':
var len = chunk.readUInt32BE(nameLen + 6);
var port = chunk.readUInt32BE(nameLen + 10 + len);
//console.log("[" + chunk.length + "/" + len + "] APF_GLOBAL_REQUEST for: " + name + " on port " + port);
if (this[name] == undefined) {
this[name] = {};
}
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
}
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);
});
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(81, 0);
outBuffer.writeUInt32BE(port, 1);
this.write(outBuffer);
break;
case 'cancel-tcpip-forward':
break;
case 'udp-send-to@amt.intel.com':
break;
default:
//console.log("Unknown APF_GLOBAL_REQUEST for: " + name);
break;
}
break;
case APF_CHANNEL_OPEN_CONFIRMATION:
var rChannel = chunk.readUInt32BE(1);
var sChannel = chunk.readUInt32BE(5);
var wSize = chunk.readUInt32BE(9);
//console.log('rChannel/' + rChannel + ', sChannel/' + sChannel + ', wSize/' + wSize);
if (this.sockets[rChannel] != undefined) {
this.sockets[rChannel].lme.amtId = sChannel;
this.sockets[rChannel].lme.rxWindow = wSize;
this.sockets[rChannel].lme.txWindow = wSize;
this.sockets[rChannel].lme.LME_CHANNEL_STATUS = 'LME_CS_CONNECTED';
//console.log('LME_CS_CONNECTED');
this.sockets[rChannel].bufferedStream = new stream_bufferedWrite();
this.sockets[rChannel].bufferedStream.socket = this.sockets[rChannel];
this.sockets[rChannel].bufferedStream.on('readable', function () {
if (this.socket.lme.txWindow > 0) {
var buffer = this.read(this.socket.lme.txWindow);
var packet = Buffer.alloc(9 + buffer.length);
packet.writeUInt8(APF_CHANNEL_DATA, 0);
packet.writeUInt32BE(this.socket.lme.amtId, 1);
packet.writeUInt32BE(buffer.length, 5);
buffer.copy(packet, 9);
this.socket.lme.txWindow -= buffer.length;
this.socket.HECI.write(packet);
}
});
this.sockets[rChannel].bufferedStream.on('drain', function () {
this.socket.resume();
});
this.sockets[rChannel].on('data', function (chunk) {
if (!this.bufferedStream.write(chunk)) { this.pause(); }
});
this.sockets[rChannel].on('end', function () {
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
outBuffer.writeUInt32BE(this.lme.amtId, 1);
this.HECI.write(outBuffer);
});
this.sockets[rChannel].resume();
}
break;
case APF_PROTOCOLVERSION:
var major = chunk.readUInt32BE(1);
var minor = chunk.readUInt32BE(5);
var reason = chunk.readUInt32BE(9);
var outBuffer = Buffer.alloc(93);
outBuffer.writeUInt8(192, 0);
outBuffer.writeUInt32BE(1, 1);
outBuffer.writeUInt32BE(0, 5);
outBuffer.writeUInt32BE(reason, 9);
//console.log('Answering PROTOCOL_VERSION');
this.write(outBuffer);
break;
case APF_CHANNEL_WINDOW_ADJUST:
var rChannelId = chunk.readUInt32BE(1);
var bytesToAdd = chunk.readUInt32BE(5);
if (this.sockets[rChannelId] != undefined) {
this.sockets[rChannelId].lme.txWindow += bytesToAdd;
if (!this.sockets[rChannelId].bufferedStream.isEmpty() && this.sockets[rChannelId].bufferedStream.isWaiting()) {
this.sockets[rChannelId].bufferedStream.emit('readable');
}
} else {
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
}
break;
case APF_CHANNEL_DATA:
var rChannelId = chunk.readUInt32BE(1);
var dataLen = chunk.readUInt32BE(5);
var data = chunk.slice(9, 9 + dataLen);
if (this.sockets[rChannelId] != undefined) {
this.sockets[rChannelId].pendingBytes.push(data.length);
this.sockets[rChannelId].write(data, function () {
var written = this.pendingBytes.shift();
var outBuffer = Buffer.alloc(9);
outBuffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
outBuffer.writeUInt32BE(this.lme.amtId, 1);
outBuffer.writeUInt32BE(written, 5);
this.HECI.write(outBuffer);
});
} else {
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
}
break;
case APF_CHANNEL_CLOSE:
var rChannelId = chunk.readUInt32BE(1);
if (this.sockets[rChannelId] != undefined) {
this.sockets[rChannelId].end();
var amtId = this.sockets[rChannelId].lme.amtId;
var buffer = Buffer.alloc(5);
delete this.sockets[rChannelId];
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
buffer.writeUInt32BE(amtId, 1);
this.write(buffer);
} else {
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_CLOSE');
}
break;
}
});
});
this.bindDuplexStream = function (duplexStream, remoteFamily, localPort) {
var socket = duplexStream;
//console.log('New [' + remoteFamily + '] Virtual Connection/' + socket.localPort);
socket.pendingBytes = [];
socket.HECI = this._LME;
socket.LMS = this;
socket.lme = new lme_object();
socket.lme.Socket = socket;
var buffer = new MemoryStream();
buffer.writeUInt8(0x5A);
buffer.writeUInt32BE(15);
buffer.write('forwarded-tcpip');
buffer.writeUInt32BE(socket.lme.ourId);
buffer.writeUInt32BE(this.INITIAL_RXWINDOW_SIZE);
buffer.writeUInt32BE(0xFFFFFFFF);
for (var i = 0; i < 2; ++i) {
if (remoteFamily == 'IPv6') {
buffer.writeUInt32BE(3);
buffer.write('::1');
} else {
buffer.writeUInt32BE(9);
buffer.write('127.0.0.1');
}
buffer.writeUInt32BE(localPort);
}
this._LME.write(buffer.buffer);
if (this._LME.sockets == undefined) { this._LME.sockets = {}; }
this._LME.sockets[socket.lme.ourId] = socket;
socket.pause();
};
this._LME.connect(heci.GUIDS.LME, { noPipeline: 0 });
}
module.exports = lme_heci;

View File

@ -0,0 +1,297 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var Q = require('queue');
function amt_heci() {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci');
this._amt = heci.create();
this._amt.BiosVersionLen = 65;
this._amt.UnicodeStringLen = 20;
this._amt.rq = new Q();
this._amt.Parent = this;
this._amt.on('error', function (e) { this.Parent.emit('error', e); });
this._amt.on('connect', function () {
this.Parent.emit('connect');
this.on('data', function (chunk) {
//console.log("Received: " + chunk.length + " bytes");
var header = this.Parent.getCommand(chunk);
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
var user = this.rq.deQueue();
var params = user.optional;
var callback = user.func;
params.unshift(header);
callback.apply(this.Parent, params);
});
});
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
this.getCommand = function (chunk) {
var command = chunk.length == 0 ? (this._amt.rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
var ret = { IsResponse: (command & 0x800000) == 0x800000 ? true : false, Command: (command & 0x7FFFFF), Status: chunk.length != 0 ? chunk.readUInt32LE(12) : -1, Data: chunk.length != 0 ? chunk.slice(16) : null };
return (ret);
};
this.sendCommand = function () {
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
var args = [];
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
this._amt.rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args });
var header = Buffer.from('010100000000000000000000', 'hex');
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
this._amt.write(arguments[1] == null ? header : Buffer.concat([header, arguments[1]]));
}
this.getVersion = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
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) {
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));
}
opt.unshift(val);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getProvisioningState = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(17, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.state = header.Data.readUInt32LE(0);
if (result.state < 3) { result.stateStr = ["PRE", "IN", "POST"][result.state]; }
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getProvisioningMode = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(8, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.mode = header.Data.readUInt32LE(0);
if (result.mode < 4) { result.modeStr = ["NONE", "ENTERPRISE", "SMALL_BUSINESS", "REMOTE_ASSISTANCE"][result.mode]; }
result.legacy = header.Data.readUInt32LE(4) == 0 ? false : true;
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getEHBCState = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(132, null, function (header, fn, opt) {
if (header.Status == 0) {
opt.unshift({ EHBC: header.Data.readUInt32LE(0) != 0 });
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getControlMode = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(107, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.controlMode = header.Data.readUInt32LE(0);
if (result.controlMode < 3) { result.controlModeStr = ["NONE_RPAT", "CLIENT", "ADMIN", "REMOTE_ASSISTANCE"][result.controlMode]; }
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getMACAddresses = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(37, null, function (header, fn, opt) {
if (header.Status == 0) {
opt.unshift({ DedicatedMAC: header.Data.slice(0, 6).toString('hex:'), HostMAC: header.Data.slice(6, 12).toString('hex:') });
} else { opt.unshift({ DedicatedMAC: null, HostMAC: null }); }
fn.apply(this, opt);
}, callback, optional);
};
this.getDnsSuffix = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(54, null, function (header, fn, opt) {
if (header.Status == 0) {
var resultLen = header.Data.readUInt16LE(0);
if (resultLen > 0) { opt.unshift(header.Data.slice(2, 2 + resultLen).toString()); } else { opt.unshift(null); }
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getHashHandles = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x2C, null, function (header, fn, opt) {
var result = [];
if (header.Status == 0) {
var resultLen = header.Data.readUInt32LE(0);
for (var i = 0; i < resultLen; ++i) {
result.push(header.Data.readUInt32LE(4 + (4 * i)));
}
}
opt.unshift(result);
fn.apply(this, opt);
}, callback, optional);
};
this.getCertHashEntry = function (handle, callback) {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
var data = new Buffer(4);
data.writeUInt32LE(handle, 0);
this.sendCommand(0x2D, data, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.isDefault = header.Data.readUInt32LE(0);
result.isActive = header.Data.readUInt32LE(4);
result.hashAlgorithm = header.Data.readUInt8(72);
if (result.hashAlgorithm < 4) {
result.hashAlgorithmStr = ["MD5", "SHA1", "SHA256", "SHA512"][result.hashAlgorithm];
result.hashAlgorithmSize = [16, 20, 32, 64][result.hashAlgorithm];
result.certificateHash = header.Data.slice(8, 8 + result.hashAlgorithmSize).toString('hex');
}
result.name = header.Data.slice(73 + 2, 73 + 2 + header.Data.readUInt16LE(73)).toString();
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getCertHashEntries = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.getHashHandles(function (handles, fn, opt) {
var entries = [];
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
}, callback, optional);
};
this._getHashEntrySink = function (result, fn, opt, entries, handles) {
entries.push(result);
if (handles.length > 0) {
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
} else {
opt.unshift(entries);
fn.apply(this, opt);
}
}
this.getLocalSystemAccount = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
if (header.Data.length == 68) { opt.unshift({ user: header.Data.slice(0, 34).toString(), pass: header.Data.slice(34, 67).toString(), raw: header.Data }); } else { opt.unshift(null); }
fn.apply(this, opt);
}, callback, optional);
}
this.unprovision = function (mode, callback) {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
var data = new Buffer(4);
data.writeUInt32LE(mode, 0);
this.sendCommand(16, data, function (header, fn, opt) {
opt.unshift(header.Status);
fn.apply(this, opt);
}, callback, optional);
}
this.startConfiguration = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x29, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.stopConfiguration = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x5E, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.openUserInitiatedConnection = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x44, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.closeUserInitiatedConnection = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x45, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.getRemoteAccessConnectionStatus = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x46, data, function (header, fn, opt) {
if (header.Status == 0) {
var hostname = v.slice(14, header.Data.readUInt16LE(12) + 14).toString()
opt.unshift({ status: header.Status, networkStatus: header.Data.readUInt32LE(0), remoteAccessStatus: header.Data.readUInt32LE(4), remoteAccessTrigger: header.Data.readUInt32LE(8), mpsHostname: hostname, raw: header.Data });
} else {
opt.unshift({ status: header.Status });
}
fn.apply(this, opt);
}, callback, optional);
}
this.getProtocolVersion = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
if (status == 0) {
var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
opt.unshift(result);
fn.apply(self, opt);
}
else {
opt.unshift(null);
fn.apply(self, opt);
}
}, this, callback, optional);
}
}
module.exports = amt_heci;

View File

@ -0,0 +1,272 @@
var MemoryStream = require('MemoryStream');
var WindowsWireless = new Buffer([
0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x5F, 0x53, 0x63, 0x61, 0x6E, 0x28, 0x29, 0x0A, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x77, 0x6C, 0x61, 0x6E,
0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x57, 0x6C, 0x61, 0x6E, 0x45,
0x6E, 0x75, 0x6D, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x77, 0x6C,
0x61, 0x6E, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x3D, 0x20,
0x77, 0x6C, 0x61, 0x6E, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x30, 0x2C, 0x20,
0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x20, 0x3D, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x49, 0x6E, 0x74, 0x65,
0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x38, 0x2C, 0x20, 0x35, 0x33, 0x32, 0x29, 0x3B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6E, 0x61, 0x6D, 0x65, 0x20, 0x3D, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x31, 0x36, 0x2C, 0x20, 0x35, 0x31, 0x32,
0x29, 0x2E, 0x41, 0x6E, 0x73, 0x69, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3B, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x28, 0x69, 0x6E, 0x66, 0x6F, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x35, 0x32, 0x38, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61,
0x6C, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x30, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x4E, 0x4F, 0x54, 0x20, 0x52, 0x45, 0x41, 0x44, 0x59, 0x22, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x31, 0x3A, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x45, 0x44, 0x22, 0x3B, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20,
0x32, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x41, 0x44, 0x2D, 0x48, 0x4F, 0x43, 0x22,
0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73,
0x65, 0x20, 0x33, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x44, 0x49, 0x53, 0x43, 0x4F,
0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x22, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x34, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65,
0x20, 0x3D, 0x20, 0x22, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x45, 0x44, 0x22, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x35, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x41, 0x53, 0x53, 0x4F, 0x43, 0x49, 0x41, 0x54, 0x49, 0x4E, 0x47, 0x22, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x36, 0x3A, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x56, 0x45, 0x52, 0x49, 0x4E, 0x47, 0x22, 0x3B,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65,
0x20, 0x37, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x22, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4E,
0x54, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4E, 0x47, 0x22, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x3B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x3A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74,
0x65, 0x20, 0x3D, 0x20, 0x22, 0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x4E, 0x22, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B,
0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x67, 0x75, 0x69, 0x64, 0x20, 0x3D, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x2E, 0x44, 0x65,
0x72, 0x65, 0x66, 0x28, 0x30, 0x2C, 0x20, 0x31, 0x36, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E,
0x57, 0x6C, 0x61, 0x6E, 0x53, 0x63, 0x61, 0x6E, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x2C, 0x20, 0x69, 0x67, 0x75, 0x69, 0x64, 0x2C, 0x20, 0x30, 0x2C, 0x20,
0x30, 0x2C, 0x20, 0x30, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E,
0x20, 0x28, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x28, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x7D, 0x0A, 0x0A, 0x66,
0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x28, 0x5F, 0x73, 0x73, 0x69, 0x64, 0x2C, 0x20, 0x5F, 0x62, 0x73, 0x73, 0x69,
0x64, 0x2C, 0x20, 0x5F, 0x72, 0x73, 0x73, 0x69, 0x2C, 0x20, 0x5F, 0x6C, 0x71, 0x29, 0x0A, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x73, 0x73, 0x69, 0x64, 0x20, 0x3D,
0x20, 0x5F, 0x73, 0x73, 0x69, 0x64, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x62, 0x73, 0x73, 0x69, 0x64, 0x20, 0x3D, 0x20, 0x5F, 0x62, 0x73, 0x73, 0x69, 0x64, 0x3B,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x72, 0x73, 0x73, 0x69, 0x20, 0x3D, 0x20, 0x5F, 0x72, 0x73, 0x73, 0x69, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73,
0x2E, 0x6C, 0x71, 0x20, 0x3D, 0x20, 0x5F, 0x6C, 0x71, 0x3B, 0x0A, 0x7D, 0x0A, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x2E, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x74, 0x79,
0x70, 0x65, 0x2E, 0x74, 0x6F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x3D, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x28, 0x29, 0x0A, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x73, 0x73, 0x69, 0x64, 0x20, 0x2B, 0x20, 0x22, 0x20, 0x5B, 0x22, 0x20, 0x2B, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x62,
0x73, 0x73, 0x69, 0x64, 0x20, 0x2B, 0x20, 0x22, 0x5D, 0x3A, 0x20, 0x22, 0x20, 0x2B, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x6C, 0x71, 0x29, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x66, 0x75, 0x6E, 0x63,
0x74, 0x69, 0x6F, 0x6E, 0x20, 0x4F, 0x6E, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x28, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x61, 0x74, 0x61, 0x29, 0x0A,
0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x3D, 0x20, 0x4E,
0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x61, 0x74, 0x61, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x30, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x3D, 0x20, 0x4E, 0x6F, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x61, 0x74, 0x61, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x34, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x47, 0x75, 0x69, 0x64, 0x20, 0x3D, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x61, 0x74,
0x61, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x38, 0x2C, 0x20, 0x31, 0x36, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x28, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x26, 0x20, 0x30, 0x58, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x4E,
0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x37, 0x29, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x73, 0x73, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x50, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68,
0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20,
0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x50, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x47, 0x65, 0x74, 0x42,
0x53, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x50, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x2E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x47,
0x75, 0x69, 0x64, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x33, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x53, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x62, 0x73, 0x73, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28,
0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x30, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76,
0x61, 0x72, 0x20, 0x6E, 0x75, 0x6D, 0x49, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x3D, 0x20, 0x62, 0x73, 0x73, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28,
0x34, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x28, 0x69, 0x20, 0x3D, 0x20,
0x30, 0x3B, 0x20, 0x69, 0x20, 0x3C, 0x20, 0x6E, 0x75, 0x6D, 0x49, 0x74, 0x65, 0x6D, 0x73, 0x3B, 0x20, 0x2B, 0x2B, 0x69, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x20, 0x62,
0x73, 0x73, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x38, 0x20, 0x2B, 0x20, 0x28, 0x33, 0x36, 0x30, 0x20, 0x2A, 0x20, 0x69, 0x29, 0x2C, 0x20,
0x33, 0x36, 0x30, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x73, 0x73, 0x69, 0x64, 0x20, 0x3D,
0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x34, 0x2C, 0x20, 0x33, 0x32, 0x29, 0x2E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x2E, 0x74, 0x72, 0x69, 0x6D, 0x28, 0x29,
0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x73, 0x73, 0x69, 0x64, 0x20, 0x3D, 0x20, 0x69, 0x74,
0x65, 0x6D, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x34, 0x30, 0x2C, 0x20, 0x36, 0x29, 0x2E, 0x48, 0x65, 0x78, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x32, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x73, 0x73, 0x69, 0x20, 0x3D, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x44, 0x65, 0x72, 0x65,
0x66, 0x28, 0x35, 0x36, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61,
0x72, 0x20, 0x6C, 0x71, 0x20, 0x3D, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x36, 0x30, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x50, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x2E, 0x65, 0x6D, 0x69, 0x74, 0x28,
0x27, 0x53, 0x63, 0x61, 0x6E, 0x27, 0x2C, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x28, 0x73, 0x73, 0x69, 0x64, 0x2C, 0x20, 0x62, 0x73,
0x73, 0x69, 0x64, 0x2C, 0x20, 0x72, 0x73, 0x73, 0x69, 0x2C, 0x20, 0x6C, 0x71, 0x29, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x7D, 0x0A, 0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x57, 0x69, 0x72, 0x65,
0x6C, 0x65, 0x73, 0x73, 0x28, 0x29, 0x0A, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x65, 0x6D, 0x69, 0x74, 0x74, 0x65, 0x72, 0x55, 0x74, 0x69, 0x6C, 0x73, 0x20, 0x3D, 0x20,
0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x27, 0x29, 0x2E, 0x69, 0x6E, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29,
0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x20, 0x3D, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x5F,
0x47, 0x65, 0x6E, 0x65, 0x72, 0x69, 0x63, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x27, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76,
0x65, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6F,
0x78, 0x79, 0x28, 0x22, 0x77, 0x6C, 0x61, 0x6E, 0x61, 0x70, 0x69, 0x2E, 0x64, 0x6C, 0x6C, 0x22, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69,
0x76, 0x65, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x28, 0x22, 0x57, 0x6C, 0x61, 0x6E, 0x4F, 0x70, 0x65, 0x6E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x22,
0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x28,
0x22, 0x57, 0x6C, 0x61, 0x6E, 0x47, 0x65, 0x74, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x42, 0x73, 0x73, 0x4C, 0x69, 0x73, 0x74, 0x22, 0x2C, 0x20, 0x22, 0x47, 0x65, 0x74, 0x42, 0x53, 0x53,
0x4C, 0x69, 0x73, 0x74, 0x22, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4D, 0x65,
0x74, 0x68, 0x6F, 0x64, 0x28, 0x22, 0x57, 0x6C, 0x61, 0x6E, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x29,
0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x28, 0x22,
0x57, 0x6C, 0x61, 0x6E, 0x45, 0x6E, 0x75, 0x6D, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x22, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E,
0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x28, 0x22, 0x57, 0x6C, 0x61, 0x6E, 0x53, 0x63, 0x61, 0x6E, 0x22, 0x29, 0x3B, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x28, 0x22, 0x57, 0x6C,
0x61, 0x6E, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6E, 0x65, 0x67,
0x6F, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69,
0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x68, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C,
0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69,
0x76, 0x65, 0x2E, 0x57, 0x6C, 0x61, 0x6E, 0x4F, 0x70, 0x65, 0x6E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x28, 0x32, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x6E, 0x65, 0x67, 0x6F, 0x74, 0x69, 0x61, 0x74,
0x65, 0x64, 0x2C, 0x20, 0x68, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x3D, 0x20, 0x68, 0x2E, 0x56, 0x61, 0x6C, 0x3B,
0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x5F, 0x4E, 0x4F, 0x54, 0x49, 0x46, 0x59, 0x5F, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x5F, 0x4F, 0x42, 0x4A, 0x45, 0x43, 0x54, 0x20,
0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6C, 0x6C, 0x62, 0x61, 0x63, 0x6B, 0x50, 0x72, 0x6F,
0x78, 0x79, 0x28, 0x4F, 0x6E, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x2C, 0x20, 0x32, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x5F, 0x4E, 0x4F, 0x54, 0x49, 0x46,
0x59, 0x5F, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x5F, 0x4F, 0x42, 0x4A, 0x45, 0x43, 0x54, 0x2E, 0x50, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x50, 0x72, 0x65, 0x76, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x20,
0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x57, 0x6C, 0x61, 0x6E, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x2C, 0x20, 0x30, 0x58, 0x30, 0x30, 0x30, 0x30, 0x46, 0x46, 0x46, 0x46, 0x2C, 0x20,
0x30, 0x2C, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x5F, 0x4E, 0x4F, 0x54, 0x49, 0x46, 0x59, 0x5F, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x5F, 0x4F, 0x42, 0x4A, 0x45, 0x43, 0x54, 0x2E, 0x43, 0x61, 0x6C,
0x6C, 0x62, 0x61, 0x63, 0x6B, 0x2C, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x5F, 0x4E, 0x4F, 0x54, 0x49, 0x46, 0x59, 0x5F, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x5F, 0x4F, 0x42, 0x4A, 0x45, 0x43, 0x54,
0x2E, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x50, 0x72, 0x65, 0x76, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6D, 0x69,
0x74, 0x74, 0x65, 0x72, 0x55, 0x74, 0x69, 0x6C, 0x73, 0x2E, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x28, 0x27, 0x53, 0x63, 0x61, 0x6E, 0x27, 0x29, 0x3B, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x65, 0x6D, 0x69, 0x74, 0x74, 0x65, 0x72, 0x55, 0x74, 0x69, 0x6C, 0x73, 0x2E, 0x61, 0x64, 0x64, 0x4D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x28, 0x27, 0x53, 0x63, 0x61, 0x6E, 0x27,
0x2C, 0x20, 0x5F, 0x53, 0x63, 0x61, 0x6E, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x47, 0x65, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x65, 0x64,
0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x3D, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x28, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61,
0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73,
0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x57, 0x6C, 0x61, 0x6E, 0x45, 0x6E, 0x75, 0x6D, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2E,
0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x3D, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x2E,
0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x30, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x20, 0x3D, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44,
0x65, 0x72, 0x65, 0x66, 0x28, 0x38, 0x2C, 0x20, 0x35, 0x33, 0x32, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6E, 0x61, 0x6D, 0x65, 0x20,
0x3D, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x31, 0x36, 0x2C, 0x20, 0x35, 0x31, 0x32, 0x29, 0x2E, 0x41, 0x6E, 0x73, 0x69, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67,
0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x2E, 0x44, 0x65, 0x72, 0x65,
0x66, 0x28, 0x35, 0x32, 0x38, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x49, 0x6E, 0x74, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x28, 0x69, 0x6E,
0x66, 0x6F, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x35, 0x32, 0x38, 0x2C, 0x20, 0x34, 0x29, 0x2E, 0x49, 0x6E, 0x74, 0x56, 0x61, 0x6C, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x29, 0x20, 0x2F, 0x2F,
0x20, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x45, 0x44, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x76, 0x61, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x53, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x70, 0x44,
0x61, 0x74, 0x61, 0x20, 0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72,
0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x20,
0x74, 0x68, 0x69, 0x73, 0x2E, 0x4D, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6C, 0x2E, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x28, 0x29, 0x3B, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x67, 0x75, 0x69, 0x64, 0x20, 0x3D, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66,
0x28, 0x30, 0x2C, 0x20, 0x31, 0x36, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x74, 0x56, 0x61, 0x6C, 0x20,
0x3D, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x4E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2E, 0x57, 0x6C, 0x61, 0x6E, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65,
0x28, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x2C, 0x20, 0x69, 0x67, 0x75, 0x69, 0x64, 0x2C, 0x20, 0x37, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x53,
0x69, 0x7A, 0x65, 0x2C, 0x20, 0x70, 0x44, 0x61, 0x74, 0x61, 0x2C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x74, 0x56, 0x61, 0x6C, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x69, 0x61, 0x74, 0x65,
0x64, 0x53, 0x53, 0x49, 0x44, 0x20, 0x3D, 0x20, 0x70, 0x44, 0x61, 0x74, 0x61, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x35, 0x32, 0x34, 0x2C,
0x20, 0x33, 0x32, 0x29, 0x2E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72,
0x20, 0x62, 0x73, 0x73, 0x69, 0x64, 0x20, 0x3D, 0x20, 0x70, 0x44, 0x61, 0x74, 0x61, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x35, 0x36, 0x30,
0x2C, 0x20, 0x36, 0x29, 0x2E, 0x48, 0x65, 0x78, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x76, 0x61, 0x72, 0x20, 0x6C, 0x71, 0x20, 0x3D, 0x20, 0x70, 0x44, 0x61, 0x74, 0x61, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x29, 0x2E, 0x44, 0x65, 0x72, 0x65, 0x66, 0x28, 0x35, 0x37, 0x36,
0x2C, 0x20, 0x34, 0x29, 0x2E, 0x49, 0x6E, 0x74, 0x56, 0x61, 0x6C, 0x3B, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6E, 0x20, 0x28, 0x6E, 0x65, 0x77, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x28, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64,
0x53, 0x53, 0x49, 0x44, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x69, 0x64, 0x2C, 0x20, 0x30, 0x2C, 0x20, 0x6C, 0x71, 0x29, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x72, 0x6F, 0x77, 0x20, 0x28, 0x22, 0x47, 0x65,
0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x73, 0x3A, 0x20, 0x46, 0x41, 0x49, 0x4C, 0x45, 0x44, 0x20, 0x28, 0x6E, 0x6F, 0x74, 0x20,
0x61, 0x73, 0x73, 0x6F, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x61, 0x20, 0x6E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x29, 0x22, 0x29, 0x3B, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x7D, 0x3B, 0x0A, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x6D, 0x6F, 0x64, 0x75, 0x6C,
0x65, 0x2E, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x20, 0x3D, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x57, 0x69, 0x72, 0x65, 0x6C, 0x65, 0x73, 0x73, 0x28, 0x29, 0x3B, 0x0A]);
var WindowsChildScript = new Buffer([
0x76, 0x61, 0x72, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6F, 0x6E, 0x74,
0x61, 0x69, 0x6E, 0x65, 0x72, 0x27, 0x29, 0x3B, 0x0D, 0x0A, 0x76, 0x61, 0x72, 0x20, 0x57, 0x69, 0x72, 0x65, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x3D, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
0x28, 0x27, 0x57, 0x69, 0x72, 0x65, 0x6C, 0x65, 0x73, 0x73, 0x27, 0x29, 0x3B, 0x0D, 0x0A, 0x0D, 0x0A, 0x57, 0x69, 0x72, 0x65, 0x6C, 0x65, 0x73, 0x73, 0x2E, 0x6F, 0x6E, 0x28, 0x27, 0x53, 0x63,
0x61, 0x6E, 0x27, 0x2C, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x28, 0x61, 0x70, 0x29, 0x20, 0x7B, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x2E, 0x73, 0x65, 0x6E, 0x64,
0x28, 0x61, 0x70, 0x29, 0x3B, 0x20, 0x7D, 0x29, 0x3B, 0x0D, 0x0A, 0x57, 0x69, 0x72, 0x65, 0x6C, 0x65, 0x73, 0x73, 0x2E, 0x53, 0x63, 0x61, 0x6E, 0x28, 0x29, 0x3B, 0x0D, 0x0A]);
function AccessPoint(_ssid, _bssid, _lq)
{
this.ssid = _ssid;
this.bssid = _bssid;
this.lq = _lq;
}
AccessPoint.prototype.toString = function ()
{
return ("[" + this.bssid + "]: " + this.ssid + " (" + this.lq + ")");
//return (this.ssid + " [" + this.bssid + "]: " + this.lq);
}
function WiFiScanner()
{
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('accessPoint');
this.hasWireless = function ()
{
var retVal = false;
var interfaces = require('os').networkInterfaces();
for (var name in interfaces)
{
if (interfaces[name][0].type == 'wireless') { retVal = true; break; }
}
return (retVal);
};
this.Scan = function ()
{
if (process.platform == 'win32')
{
this.master = require('ScriptContainer').Create(15, ContainerPermissions.DEFAULT);
this.master.parent = this;
this.master.on('data', function (j) { this.parent.emit('accessPoint', new AccessPoint(j.ssid, j.bssid, j.lq)); });
this.master.addModule('Wireless', WindowsWireless.toString());
this.master.ExecuteString(WindowsChildScript.toString());
}
else if (process.platform == 'linux')
{
// Need to get the wireless interface name
var interfaces = require('os').networkInterfaces();
var wlan = null;
for (var i in interfaces)
{
if (interfaces[i][0].type == 'wireless')
{
wlan = i;
break;
}
}
if (wlan != null)
{
this.child = require('child_process').execFile('/sbin/iwlist', ['iwlist', wlan, 'scan']);
this.child.parent = this;
this.child.ms = new MemoryStream();
this.child.ms.parent = this.child;
this.child.stdout.on('data', function (buffer) { this.parent.ms.write(buffer); });
this.child.on('exit', function () { this.ms.end(); });
this.child.ms.on('end', function ()
{
var str = this.buffer.toString();
tokens = str.split(' - Address: ');
for (var block in tokens)
{
if (block == 0) continue;
var ln = tokens[block].split('\n');
var _bssid = ln[0];
var _lq;
var _ssid;
for (var lnblock in ln)
{
lnblock = ln[lnblock].trim();
lnblock = lnblock.trim();
if (lnblock.startsWith('ESSID:'))
{
_ssid = lnblock.slice(7, lnblock.length - 1);
if (_ssid == '<hidden>') { _ssid = ''; }
}
if (lnblock.startsWith('Signal level='))
{
_lq = lnblock.slice(13,lnblock.length-4);
}
else if (lnblock.startsWith('Quality='))
{
_lq = lnblock.slice(8, 10);
var scale = lnblock.slice(11, 13);
}
}
this.parent.parent.emit('accessPoint', new AccessPoint(_ssid, _bssid, _lq));
}
});
}
}
}
}
module.exports = WiFiScanner;

View File

@ -21,7 +21,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
if (obj.args.tlsoffload) {
obj.server = net.createServer(onConnection);
} else {
obj.server = tls.createServer({ key: certificates.mps.key, cert: certificates.mps.cert, requestCert: true }, onConnection);
obj.server = tls.createServer({ key: certificates.mps.key, cert: certificates.mps.cert, requestCert: true, rejectUnauthorized: false }, onConnection);
}
obj.server.listen(args.mpsport, function () { console.log('MeshCentral Intel(R) AMT server running on ' + certificates.CommonName + ':' + args.mpsport + '.'); }).on('error', function (err) { console.error('ERROR: MeshCentral Intel(R) AMT server port ' + args.mpsport + ' is not available.'); if (args.exactports) { process.exit(); } });

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.1.3-j",
"version": "0.1.3-r",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -3358,7 +3358,12 @@
p13filetree = data;
p13updateFiles(checkedNames);
} else {
if ((data.path.replace(/\//g, "\\") == p13targetpath.replace(/\//g, "\\")) || ((data.path == '\\') && (p13targetpath == ''))) {
// Make both paths use the same seperator not start with /
var x1 = data.path.replace(/\//g, "\\");
var x2 = p13targetpath.replace(/\//g, "\\");
while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
// This is a different folder
p13filetree = data;
p13updateFiles();

View File

@ -1404,6 +1404,10 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
obj.handleMeshAgentRequest = function (req, res) {
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
// If required, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true) && (req.session.userid == null)) { res.sendStatus(401); return; }
if (req.query.id != null) {
// Send a specific mesh agent back
var argentInfo = obj.parent.meshAgentBinaries[req.query.id];
@ -1418,10 +1422,12 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
if (meshes.length != 1) { res.sendStatus(401); return; }
var mesh = meshes[0];
// Check if this user has rights to do this
//var user = obj.users[req.session.userid];
//if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
//if (domain.id != mesh.domain) { res.sendStatus(401); return; }
// If required, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid];
if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
}
var meshidhex = new Buffer(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
@ -1449,19 +1455,6 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') });
res.statusCode = 200;
obj.parent.exeHandler.streamExeWithJavaScript({ platform: argentInfo.platform, sourceFileName: argentInfo.path, destinationStream: res, js: new Buffer(obj.parent.defaultMeshCmd, 'utf8'), peinfo: argentInfo.pe });
/*
// Load the agent
obj.fs.readFile(argentInfo.path, function (err, agentexe) {
if (err != null) { res.sendStatus(404); return; }
// Send out merged meshcmd
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') });
var meshcmdbuf = new Buffer(obj.parent.defaultMeshCmd, 'utf8'), tail = new Buffer(8);
tail.writeInt32BE(meshcmdbuf.length, 0);
tail.writeInt32BE(agentexe.length + meshcmdbuf.length + 8, 4);
res.send(Buffer.concat([agentexe, meshcmdbuf, tail]));
});
*/
} else if (req.query.meshaction != null) {
var domain = checkUserIpAddress(req, res);
if (domain == null) { res.sendStatus(404); return; }
@ -1531,16 +1524,21 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
//if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
// If required, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true) && (req.session.userid == null)) { res.sendStatus(401); return; }
// Query the meshid
obj.db.Get('mesh/' + domain.id + '/' + req.query.id, function (err, meshes) {
if (meshes.length != 1) { res.sendStatus(401); return; }
var mesh = meshes[0];
// Check if this user has rights to do this
//var user = obj.users[req.session.userid];
//if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
//if (domain.id != mesh.domain) { res.sendStatus(401); return; }
// If needed, check if this user has rights to do this
if ((obj.parent.config.settings != null) && (obj.parent.config.settings.lockagentdownload == true)) {
var user = obj.users[req.session.userid];
if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
}
var meshidhex = new Buffer(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();