diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 30c2aee3..af3aa023 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index 6e81287b..60c239bf 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/meshcmd.js b/agents/meshcmd.js index 1cd8e3a2..18381ac5 100644 --- a/agents/meshcmd.js +++ b/agents/meshcmd.js @@ -45,7 +45,7 @@ var wsstack = null, amtstack = null; var oswsstack = null, osamtstack = null; var amtMeiTmpState = null; var SMBiosTables = null; -var globalDebugFlags = 0; +var globalDebugFlags = 0; // 1 = IDER Debug const RCSMessageProtocolVersion = 1; // RCS Message Protocol Version. Needs to be less than or equal to RCS server Message Protocol Version // MeshCommander for Firmware (GZIP'ed, Base64) v0.7.5 @@ -128,6 +128,10 @@ function run(argv) { if ((typeof args.script) == 'string') { settings.script = args.script; } if ((typeof args.agent) == 'string') { settings.agent = args.agent; } if ((typeof args.proxy) == 'string') { settings.proxy = args.proxy; } + if ((typeof args.floppy) == 'string') { settings.floppy = args.floppy; } + if ((typeof args.cdrom) == 'string') { settings.cdrom = args.cdrom; } + if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); } + if (args.debug === true) { settings.debuglevel = 1; } if (args.debug) { try { waitForDebugger(); } catch (e) { } } if (args.noconsole) { settings.noconsole = true; } if (args.nocommander) { settings.noconsole = true; } @@ -163,6 +167,7 @@ function run(argv) { console.log(' AmtSaveState - Save all Intel AMT WSMAN object to file.'); console.log(' AmtPresence - Heartbeat a local Intel AMT watchdog agent.'); console.log(' AmtScript - Run .mescript on Intel AMT.'); + console.log(' AmtIDER - Mount local disk image to remote computer.'); console.log('\r\nHelp on a specific action using:\r\n'); console.log(' meshcmd help [action]'); exit(1); return; @@ -274,6 +279,16 @@ function run(argv) { console.log(' --user [username] The Intel AMT login username, admin is default.'); console.log(' --pass [password] The Intel AMT login password.'); console.log(' --tls Specifies that TLS must be used.'); + } else if (action == 'amtider') { + console.log('AmtIDER will mount a local disk images to a remote Intel AMT computer. Example usage:\r\n\r\n meshcmd amtider --host 1.2.3.4 --user admin --pass mypassword --tls --floppy disk.img --cdrom disk.iso'); + console.log('\r\nPossible arguments:\r\n'); + console.log(' --host [hostname] The IP address or DNS name of Intel AMT.'); + console.log(' --user [username] The Intel AMT login username, admin is default.'); + console.log(' --pass [password] The Intel AMT login password.'); + console.log(' --tls Specifies that TLS must be used.'); + console.log(' --floppy [file] Specifies .img file to be mounted as a flppy disk.'); + console.log(' --cdrom [file] Specifies .img file to be mounted as a CDROM disk.'); + console.log(' --timeout [seconds] Optional, disconnect after number of seconds without disk read.'); } else { actions.shift(); console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.'); @@ -492,6 +507,14 @@ function run(argv) { if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } } else { settings.hostname = '127.0.0.1'; } readAmtAuditLog(); + } else if (settings.action == 'amtider') { // Remote mount IDER image + if ((settings.hostname == null) || (typeof settings.hostname != 'string') || (settings.hostname == '')) { console.log('No or invalid \"hostname\" specified, use --hostname [password].'); exit(1); return; } + if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } + if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } + if ((settings.floppy == null) || (typeof settings.floppy != 'string') || (settings.floppy == '')) { settings.floppy = null; } + if ((settings.cdrom == null) || (typeof settings.cdrom != 'string') || (settings.cdrom == '')) { settings.cdrom = null; } + if ((settings.floppy == null) && (settings.cdrom == null)) { console.log('No or invalid \"floppy\" or \"cdrom\" specified, use --floppy [file] or --cdrom [file].'); exit(1); return; } + performIder(); } else { console.log('Invalid \"action\" specified.'); exit(1); return; } @@ -1818,6 +1841,47 @@ function deleteStorage(name, func, noretry) { req.end(); } + +// +// IDER +// + +ider = null; +iderIdleTimer = null; + +// Perform IDER +function performIder() { + if ((settings.floppy != null) && fs.existsSync(settings.floppy) == false) { console.log("Unable to floppy image file: " + settings.floppy); process.exit(); return; } + if ((settings.cdrom != null) && fs.existsSync(settings.cdrom) == false) { console.log("Unable to CDROM image file: " + settings.cdrom); process.exit(); return; } + try { + var sfloppy = null, scdrom = null; + if (settings.floppy) { try { if (sfloppy = fs.statSync(settings.floppy)) { sfloppy.file = fs.openSync(settings.floppy, 'rbN'); } } catch (ex) { console.log(ex); process.exit(1); return; } } + if (settings.cdrom) { try { scdrom = fs.statSync(settings.cdrom); if (scdrom) { scdrom.file = fs.openSync(settings.cdrom, 'rbN'); } } catch (ex) { console.log(ex); process.exit(1); return; } } + + ider = require('amt-redir-duk')(require('amt-ider')()); + ider.onStateChanged = onIderStateChange; + ider.m.floppy = sfloppy; + ider.m.cdrom = scdrom; + ider.m.iderStart = 1; // OnReboot = 0, Graceful = 1, Now = 2 + ider.m.debug = (settings.debuglevel > 0); + if (settings.timeout > 0) { ider.m.sectorStats = iderSectorStats; } + //ider.digestRealmMatch = wsstack.comm.digestRealm; + //ider.tlsv1only = amtstack.wsman.comm.tlsv1only; + ider.Start(settings.hostname, (settings.tls == true)?16995:16994, settings.username ? 'admin' : settings.username, settings.password, settings.tls); + } catch (ex) { console.log(ex); } +} + +function onIderStateChange(stack, state) { console.log(['Disconnected', 'Connecting...', 'Connected...', 'Started IDER...'][state]);} + +function iderSectorStats(mode, dev, mediaBlocks, lba, len) { + if (iderIdleTimer != null) { clearTimeout(iderIdleTimer); } + iderIdleTimer = setTimeout(function () { console.log('Idle timeout'); process.exit(1); }, 1000 * settings.timeout); +} + +// +// Startup +// + // Parse URL arguments function parseUrlArguments(url) { var r = {}, x = url.split('?'); diff --git a/agents/meshcmd.min.js b/agents/meshcmd.min.js index 1cd8e3a2..18381ac5 100644 --- a/agents/meshcmd.min.js +++ b/agents/meshcmd.min.js @@ -45,7 +45,7 @@ var wsstack = null, amtstack = null; var oswsstack = null, osamtstack = null; var amtMeiTmpState = null; var SMBiosTables = null; -var globalDebugFlags = 0; +var globalDebugFlags = 0; // 1 = IDER Debug const RCSMessageProtocolVersion = 1; // RCS Message Protocol Version. Needs to be less than or equal to RCS server Message Protocol Version // MeshCommander for Firmware (GZIP'ed, Base64) v0.7.5 @@ -128,6 +128,10 @@ function run(argv) { if ((typeof args.script) == 'string') { settings.script = args.script; } if ((typeof args.agent) == 'string') { settings.agent = args.agent; } if ((typeof args.proxy) == 'string') { settings.proxy = args.proxy; } + if ((typeof args.floppy) == 'string') { settings.floppy = args.floppy; } + if ((typeof args.cdrom) == 'string') { settings.cdrom = args.cdrom; } + if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); } + if (args.debug === true) { settings.debuglevel = 1; } if (args.debug) { try { waitForDebugger(); } catch (e) { } } if (args.noconsole) { settings.noconsole = true; } if (args.nocommander) { settings.noconsole = true; } @@ -163,6 +167,7 @@ function run(argv) { console.log(' AmtSaveState - Save all Intel AMT WSMAN object to file.'); console.log(' AmtPresence - Heartbeat a local Intel AMT watchdog agent.'); console.log(' AmtScript - Run .mescript on Intel AMT.'); + console.log(' AmtIDER - Mount local disk image to remote computer.'); console.log('\r\nHelp on a specific action using:\r\n'); console.log(' meshcmd help [action]'); exit(1); return; @@ -274,6 +279,16 @@ function run(argv) { console.log(' --user [username] The Intel AMT login username, admin is default.'); console.log(' --pass [password] The Intel AMT login password.'); console.log(' --tls Specifies that TLS must be used.'); + } else if (action == 'amtider') { + console.log('AmtIDER will mount a local disk images to a remote Intel AMT computer. Example usage:\r\n\r\n meshcmd amtider --host 1.2.3.4 --user admin --pass mypassword --tls --floppy disk.img --cdrom disk.iso'); + console.log('\r\nPossible arguments:\r\n'); + console.log(' --host [hostname] The IP address or DNS name of Intel AMT.'); + console.log(' --user [username] The Intel AMT login username, admin is default.'); + console.log(' --pass [password] The Intel AMT login password.'); + console.log(' --tls Specifies that TLS must be used.'); + console.log(' --floppy [file] Specifies .img file to be mounted as a flppy disk.'); + console.log(' --cdrom [file] Specifies .img file to be mounted as a CDROM disk.'); + console.log(' --timeout [seconds] Optional, disconnect after number of seconds without disk read.'); } else { actions.shift(); console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.'); @@ -492,6 +507,14 @@ function run(argv) { if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } } else { settings.hostname = '127.0.0.1'; } readAmtAuditLog(); + } else if (settings.action == 'amtider') { // Remote mount IDER image + if ((settings.hostname == null) || (typeof settings.hostname != 'string') || (settings.hostname == '')) { console.log('No or invalid \"hostname\" specified, use --hostname [password].'); exit(1); return; } + if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } + if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } + if ((settings.floppy == null) || (typeof settings.floppy != 'string') || (settings.floppy == '')) { settings.floppy = null; } + if ((settings.cdrom == null) || (typeof settings.cdrom != 'string') || (settings.cdrom == '')) { settings.cdrom = null; } + if ((settings.floppy == null) && (settings.cdrom == null)) { console.log('No or invalid \"floppy\" or \"cdrom\" specified, use --floppy [file] or --cdrom [file].'); exit(1); return; } + performIder(); } else { console.log('Invalid \"action\" specified.'); exit(1); return; } @@ -1818,6 +1841,47 @@ function deleteStorage(name, func, noretry) { req.end(); } + +// +// IDER +// + +ider = null; +iderIdleTimer = null; + +// Perform IDER +function performIder() { + if ((settings.floppy != null) && fs.existsSync(settings.floppy) == false) { console.log("Unable to floppy image file: " + settings.floppy); process.exit(); return; } + if ((settings.cdrom != null) && fs.existsSync(settings.cdrom) == false) { console.log("Unable to CDROM image file: " + settings.cdrom); process.exit(); return; } + try { + var sfloppy = null, scdrom = null; + if (settings.floppy) { try { if (sfloppy = fs.statSync(settings.floppy)) { sfloppy.file = fs.openSync(settings.floppy, 'rbN'); } } catch (ex) { console.log(ex); process.exit(1); return; } } + if (settings.cdrom) { try { scdrom = fs.statSync(settings.cdrom); if (scdrom) { scdrom.file = fs.openSync(settings.cdrom, 'rbN'); } } catch (ex) { console.log(ex); process.exit(1); return; } } + + ider = require('amt-redir-duk')(require('amt-ider')()); + ider.onStateChanged = onIderStateChange; + ider.m.floppy = sfloppy; + ider.m.cdrom = scdrom; + ider.m.iderStart = 1; // OnReboot = 0, Graceful = 1, Now = 2 + ider.m.debug = (settings.debuglevel > 0); + if (settings.timeout > 0) { ider.m.sectorStats = iderSectorStats; } + //ider.digestRealmMatch = wsstack.comm.digestRealm; + //ider.tlsv1only = amtstack.wsman.comm.tlsv1only; + ider.Start(settings.hostname, (settings.tls == true)?16995:16994, settings.username ? 'admin' : settings.username, settings.password, settings.tls); + } catch (ex) { console.log(ex); } +} + +function onIderStateChange(stack, state) { console.log(['Disconnected', 'Connecting...', 'Connected...', 'Started IDER...'][state]);} + +function iderSectorStats(mode, dev, mediaBlocks, lba, len) { + if (iderIdleTimer != null) { clearTimeout(iderIdleTimer); } + iderIdleTimer = setTimeout(function () { console.log('Idle timeout'); process.exit(1); }, 1000 * settings.timeout); +} + +// +// Startup +// + // Parse URL arguments function parseUrlArguments(url) { var r = {}, x = url.split('?'); diff --git a/agents/modules_meshcmd/amt-ider.js b/agents/modules_meshcmd/amt-ider.js new file mode 100644 index 00000000..45213061 --- /dev/null +++ b/agents/modules_meshcmd/amt-ider.js @@ -0,0 +1,601 @@ +/** +* @description IDER Handling Module +* @author Ylian Saint-Hilaire +*/ + +// meshservice meshcmd.js amtider --host 192.168.2.186 --pass P@ssw0rd --floppy msdos.img + +// Construct a Intel AMT IDER object +module.exports = function CreateAmtRemoteIder() { + var obj = {}; + obj.protocol = 3; // IDER + obj.bytesToAmt = 0; + obj.bytesFromAmt = 0; + obj.rx_timeout = 30000; // Default 30000 + obj.tx_timeout = 0; // Default 0 + obj.heartbeat = 20000; // Default 20000 + obj.version = 1; + obj.acc = null; + obj.inSequence = 0; + obj.outSequence = 0; + obj.iderinfo = null; + obj.enabled = false; + obj.iderStart = 0; // OnReboot = 0, Graceful = 1, Now = 2 + obj.floppy = null; + obj.cdrom = null; + obj.floppyReady = false; + obj.cdromReady = false; + //obj.pingTimer = null; + obj.sectorStats = null; + obj.debug = false; + + // Mode Sense + var IDE_ModeSence_LS120Disk_Page_Array = new Buffer([0x00, 0x26, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1E, 0x10, 0xA9, 0x08, 0x20, 0x02, 0x00, 0x03, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x00, 0x00]); + var IDE_ModeSence_3F_LS120_Array = new Buffer([0x00, 0x5c, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x16, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x1E, 0x10, 0xA9, 0x08, 0x20, 0x02, 0x00, 0x03, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x11, 0x24, 0x31]); + var IDE_ModeSence_FloppyDisk_Page_Array = new Buffer([0x00, 0x26, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1E, 0x04, 0xB0, 0x02, 0x12, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x00, 0x00]); + var IDE_ModeSence_3F_Floppy_Array = new Buffer([0x00, 0x5c, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x16, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x1e, 0x04, 0xb0, 0x02, 0x12, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd0, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x11, 0x24, 0x31]); + var IDE_ModeSence_CD_1A_Array = new Buffer([0x00, 0x12, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + //var IDE_ModeSence_CD_1B_Array = new Buffer([0x00, 0x12, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + var IDE_ModeSence_CD_1D_Array = new Buffer([0x00, 0x12, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + var IDE_ModeSence_CD_2A_Array = new Buffer([0x00, 0x20, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + //var IDE_ModeSence_CD_01_Array = new Buffer([0x00, 0x0E, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00]); + var IDE_ModeSence_3F_CD_Array = new Buffer([0x00, 0x28, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + + // 0x46 constant data + var IDE_CD_ConfigArrayHeader = new Buffer([0x00, 0x00,0x00, 0x28, 0x00, 0x00, 0x00, 0x08]); + var IDE_CD_ConfigArrayProfileList = new Buffer([0x00, 0x00, 0x03, 0x04, 0x00, 0x08, 0x01, 0x00]); + var IDE_CD_ConfigArrayCore = new Buffer([0x00, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x02]); + var IDE_CD_Morphing = new Buffer([0x00, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00]); + var IDE_CD_ConfigArrayRemovable = new Buffer([0x00, 0x03, 0x03, 0x04, 0x29, 0x00, 0x00, 0x02]); + var IDE_CD_ConfigArrayRandom = new Buffer([0x00, 0x10, 0x01, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00]); + var IDE_CD_Read = new Buffer([0x00, 0x1E, 0x03, 0x00]); + var IDE_CD_PowerManagement = new Buffer([0x01, 0x00, 0x03, 0x00]); + var IDE_CD_Timeout = new Buffer([0x01, 0x05, 0x03, 0x00]); + + // 0x01 constant data + var IDE_ModeSence_FloppyError_Recovery_Array = new Buffer([0x00, 0x12, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00]); + var IDE_ModeSence_Ls120Error_Recovery_Array = new Buffer([0x00, 0x12, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00]); + var IDE_ModeSence_CDError_Recovery_Array = new Buffer([0x00, 0x0E, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00]); + + + // Private method, called by parent when it change state + obj.xxStateChange = function (newstate) { + if (obj.debug) console.log("IDER-StateChange", newstate); + if (newstate == 0) { obj.Stop(); } + if (newstate == 3) { obj.Start(); } + } + + obj.Start = function () { + if (obj.debug) { console.log("IDER-Start"); console.log(obj.floppy, obj.cdrom); } + obj.bytesToAmt = 0; + obj.bytesFromAmt = 0; + obj.inSequence = 0; + obj.outSequence = 0; + g_readQueue = []; + + // Send first command, OPEN_SESSION + obj.SendCommand(0x40, Buffer.concat([ ShortToStrX(obj.rx_timeout), ShortToStrX(obj.tx_timeout), ShortToStrX(obj.heartbeat), IntToStrX(obj.version) ])); + + // Send sector stats + if (obj.sectorStats) { + obj.sectorStats(0, 0, obj.floppy ? (obj.floppy.size >> 9) : 0); + obj.sectorStats(0, 1, obj.cdrom ? (obj.cdrom.size >> 11) : 0); + } + + // Setup the ping timer + //obj.pingTimer = setInterval(function () { obj.SendCommand(0x44); }, 5000); + } + + obj.Stop = function () { + if (obj.debug) console.log("IDER-Stop"); + //if (obj.pingTimer) { clearInterval(obj.pingTimer); obj.pingTimer = null; } + obj.parent.Stop(); + } + + // Private method + obj.ProcessData = function (data) { + obj.bytesFromAmt += data.length; + if (obj.acc == null) { obj.acc = data; } else { obj.acc = Buffer.concat(obj.acc, data); } + if (obj.debug) console.log('IDER-ProcessData', obj.acc.length, obj.acc.toString('hex')); + + // Process as many commands as possible + while (obj.acc != null) { + var len = obj.ProcessDataEx(); + if (len == 0) return; + if (obj.inSequence != ReadIntX(obj.acc, 4)) { + if (obj.debug) console.log('ERROR: Out of sequence', obj.inSequence, ReadIntX(obj.acc, 4)); + obj.Stop(); + return; + } + obj.inSequence++; + if (len == obj.acc.length) { obj.acc = null; } else { obj.acc = obj.acc.slice(len); } + } + } + + // Private method + obj.SendCommand = function (cmdid, data, completed, dma) { + if (data == null) { data = new Buffer(0); } + var attributes = ((cmdid > 50) && (completed == true)) ? 2 : 0; + if (dma) { attributes += 1; } + var x = Buffer.concat([Buffer([cmdid, 0, 0, attributes]), IntToStrX(obj.outSequence++), data]); + obj.parent.xxSend(x); + obj.bytesToAmt += x.length; + //if (cmdid != 0x4B) { console.log('IDER-SendData', x.length, x.toString('hex')); } + } + + // CommandEndResponse (SCSI_SENSE) + obj.SendCommandEndResponse = function (error, sense, device, asc, asq) { + if (error) { obj.SendCommand(0x51, new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xc5, 0, 3, 0, 0, 0, device, 0x50, 0, 0, 0]), true); } + else { obj.SendCommand(0x51, new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87, (sense << 4), 3, 0, 0, 0, device, 0x51, sense, asc, asq]), true); } + } + + // DataToHost (SCSI_READ) + obj.SendDataToHost = function (device, completed, data, dma) { + var dmalen = (dma) ? 0 : data.length; + if (completed == true) { + obj.SendCommand(0x54, Buffer.concat([new Buffer([0, (data.length & 0xff), (data.length >> 8), 0, dma ? 0xb4 : 0xb5, 0, 2, 0, (dmalen & 0xff), (dmalen >> 8), device, 0x58, 0x85, 0, 3, 0, 0, 0, device, 0x50, 0, 0, 0, 0, 0, 0]), data ]), completed, dma); + } else { + obj.SendCommand(0x54, Buffer.concat([new Buffer([0, (data.length & 0xff), (data.length >> 8), 0, dma ? 0xb4 : 0xb5, 0, 2, 0, (dmalen & 0xff), (dmalen >> 8), device, 0x58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), data]), completed, dma); + } + } + + // GetDataFromHost (SCSI_CHUNK) + obj.SendGetDataFromHost = function (device, chunksize) { + obj.SendCommand(0x52, new Buffer([0, (chunksize & 0xff), (chunksize >> 8), 0, 0xb5, 0, 0, 0, (chunksize & 0xff), (chunksize >> 8), device, 0x58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), false); + } + + // DisableEnableFeatures (STATUS_DATA) + // If type is REGS_TOGGLE (3), 4 bytes of data must be provided. + obj.SendDisableEnableFeatures = function (type, data) { if (data == null) { data = ''; } obj.SendCommand(0x48, Buffer.concat([new Buffer([type]), data])); } + + // Private method + obj.ProcessDataEx = function () { + if (obj.acc.length < 8) return 0; + + // First 8 bytes are the header + // CommandID + 0x000000 + Sequence Number + //console.log('ProcessDataEx', obj.acc[0]); + + switch(obj.acc[0]) { + case 0x41: // OPEN_SESSION + if (obj.acc.length < 30) return 0; + var len = obj.acc[29]; + if (obj.acc.length < (30 + len)) return 0; + obj.iderinfo = {}; + obj.iderinfo.major = obj.acc[8]; + obj.iderinfo.minor = obj.acc[9]; + obj.iderinfo.fwmajor = obj.acc[10]; + obj.iderinfo.fwminor = obj.acc[11]; + obj.iderinfo.readbfr = ReadShortX(obj.acc, 16); + obj.iderinfo.writebfr = ReadShortX(obj.acc, 18); + obj.iderinfo.proto = obj.acc[21]; + obj.iderinfo.iana = ReadIntX(obj.acc, 25); + if (obj.debug) console.log(obj.iderinfo); + + if (obj.iderinfo.proto != 0) { + if (obj.debug) console.log("Unknown proto", obj.iderinfo.proto); + obj.Stop(); + } + if (obj.iderinfo.readbfr > 8192) { + if (obj.debug) console.log("Illegal read buffer size", obj.iderinfo.readbfr); + obj.Stop(); + } + if (obj.iderinfo.writebfr > 8192) { + if (obj.debug) console.log("Illegal write buffer size", obj.iderinfo.writebfr); + obj.Stop(); + } + + if (obj.iderStart == 0) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x08)); } // OnReboot + else if (obj.iderStart == 1) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x10)); } // Graceful + else if (obj.iderStart == 2) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x18)); } // Now + //obj.SendDisableEnableFeatures(1); // GetSupportedFeatures + return 30 + len; + case 0x43: // CLOSE + if (obj.debug) console.log('CLOSE'); + obj.Stop(); + return 8; + case 0x44: // KEEPALIVEPING + obj.SendCommand(0x45); // Send PONG back + return 8; + case 0x45: // KEEPALIVEPONG + if (obj.debug) console.log('PONG'); + return 8; + case 0x46: // RESETOCCURED + if (obj.acc.length < 9) return 0; + var resetMask = obj.acc[8]; + if (g_media === null) { + // No operations are pending + obj.SendCommand(0x47); // Send ResetOccuredResponse + if (obj.debug) console.log('RESETOCCURED1', resetMask); + } else { + // Operations are being done, sent the reset once completed. + g_reset = true; + if (obj.debug) console.log('RESETOCCURED2', resetMask); + } + return 9; + case 0x49: // STATUS_DATA - DisableEnableFeaturesReply + if (obj.acc.length < 13) return 0; + var type = obj.acc[8]; + var value = ReadIntX(obj.acc, 9); + if (obj.debug) console.log('STATUS_DATA', type, value); + switch (type) + { + case 1: // REGS_AVAIL + if (value & 1) { + if (obj.iderStart == 0) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x08)); } // OnReboot + else if (obj.iderStart == 1) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x10)); } // Graceful + else if (obj.iderStart == 2) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x18)); } // Now + } + break; + case 2: // REGS_STATUS + obj.enabled = (value & 2) ? true : false; + if (obj.debug) console.log("IDER Status: " + obj.enabled); + break; + case 3: // REGS_TOGGLE + if (value != 1) { + if (obj.debug) console.log("Register toggle failure"); + } //else { obj.SendDisableEnableFeatures(2); } + break; + } + return 13; + case 0x4A: // ERROR OCCURED + if (obj.acc.length < 11) return 0; + if (obj.debug) console.log('IDER: ABORT', obj.acc[8]); + //obj.Stop(); + return 11; + case 0x4B: // HEARTBEAT + //console.log('HEARTBEAT'); + return 8; + case 0x50: // COMMAND WRITTEN + if (obj.acc.length < 28) return 0; + var device = (obj.acc[14] & 0x10) ? 0xB0 : 0xA0; + var deviceFlags = obj.acc[14]; + var cdb = obj.acc.slice(16, 28); + var featureRegister = obj.acc[9]; + if (obj.debug) console.log('SCSI_CMD', device, cdb.toString('hex'), featureRegister, deviceFlags); + handleSCSI(device, cdb, featureRegister, deviceFlags); + return 28; + case 0x53: // DATA FROM HOST + if (obj.acc.length < 14) return 0; + var len = ReadShortX(obj.acc, 9); + if (obj.acc.length < (14 + len)) return 0; + if (obj.debug) console.log('SCSI_WRITE, len = ' + (14 + len)); + obj.SendCommand(0x51, new Buffer([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x70, 0x03, 0x00, 0x00, 0x00, 0xa0, 0x51, 0x07, 0x27, 0x00]), true); + return 14 + len; + default: + if (obj.debug) console.log('Unknown IDER command', obj.acc[0]); + obj.Stop(); + break; + } + return 0; + } + + function handleSCSI(dev, cdb, featureRegister, deviceFlags) + { + var lba; + var len; + + switch(cdb[0]) + { + case 0x00: // TEST_UNIT_READY: + if (obj.debug) console.log("SCSI: TEST_UNIT_READY", dev); + switch (dev) { + case 0xA0: // DEV_FLOPPY + if (obj.floppy == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; } + if (obj.floppyReady == false) { obj.floppyReady = true; obj.SendCommandEndResponse(1, 0x06, dev, 0x28, 0x00); return -1; } // Switch to ready + break; + case 0xB0: // DEV_CDDVD + if (obj.cdrom == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; } + if (obj.cdromReady == false) { obj.cdromReady = true; obj.SendCommandEndResponse(1, 0x06, dev, 0x28, 0x00); return -1; } // Switch to ready + break; + default: + if (obj.debug) console.log("SCSI Internal error 3", dev); + return -1; + } + obj.SendCommandEndResponse(1, 0x00, dev, 0x00, 0x00); // Indicate ready + break; + case 0x08: // READ_6 + lba = ((cdb[1] & 0x1f) << 16) + (cdb[2] << 8) + cdb[3]; + len = cdb[4]; + if (len == 0) { len = 256; } + if (obj.debug) console.log("SCSI: READ_6", dev, lba, len); + sendDiskData(dev, lba, len, featureRegister); + break; + case 0x0a: // WRITE_6 + lba = ((cdb[1] & 0x1f) << 16) + (cdb[2] << 8) + cdb[3]; + len = cdb[4]; + if (len == 0) { len = 256; } + if (obj.debug) console.log("SCSI: WRITE_6", dev, lba, len); + obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); // Write is not supported, remote no medium. + return -1; + /* + case 0x15: // MODE_SELECT_6: + console.log("SCSI ERROR: MODE_SELECT_6", dev); + obj.SendCommandEndResponse(1, 0x05, dev, 0x20, 0x00); + return -1; + */ + case 0x1a: // MODE_SENSE_6 + if (obj.debug) console.log("SCSI: MODE_SENSE_6", dev); + if ((cdb[2] == 0x3f) && (cdb[3] == 0x00)) { + var a = 0, b = 0; + switch (dev) { + case 0xA0: // DEV_FLOPPY + if (obj.floppy == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; } + a = 0x00; + b = 0x80; // Read only = 0x80, Read write = 0x00 + break; + case 0xB0: // DEV_CDDVD + if (obj.cdrom == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; } + a = 0x05; + b = 0x80; + break; + default: + if (obj.debug) console.log("SCSI Internal error 6", dev); + return -1; + } + obj.SendDataToHost(dev, true, new Buffer([0, a, b, 0]), featureRegister & 1); + return; + } + obj.SendCommandEndResponse(1, 0x05, dev, 0x24, 0x00); + break; + case 0x1b: // START_STOP (Called when you eject the CDROM) + //var immediate = cdb[1] & 0x01; + //var loej = cdb[4] & 0x02; + //var start = cdb[4] & 0x01; + obj.SendCommandEndResponse(1, 0, dev); + break; + case 0x1e: // LOCK_UNLOCK - ALLOW_MEDIUM_REMOVAL + if (obj.debug) console.log("SCSI: ALLOW_MEDIUM_REMOVAL", dev); + if ((dev == 0xA0) && (obj.floppy == null)) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; } + if ((dev == 0xB0) && (obj.cdrom == null)) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; } + obj.SendCommandEndResponse(1, 0x00, dev, 0x00, 0x00); + break; + case 0x23: // READ_FORMAT_CAPACITIES (Floppy only) + if (obj.debug) console.log("SCSI: READ_FORMAT_CAPACITIES", dev); + var buflen = ReadShort(cdb, 7); + var mediaStatus = 0, sectors; + var mcSize = buflen / 8; // Capacity descriptor size is 8 + + switch (dev) { + case 0xA0: // DEV_FLOPPY + if ((obj.floppy == null) || (obj.floppy.size == 0)) { obj.SendCommandEndResponse(0, 0x05, dev, 0x24, 0x00); return -1; } + sectors = (obj.floppy.size >> 9) - 1; + break; + case 0xB0: // DEV_CDDVD + if ((obj.cdrom == null) || (obj.cdrom.size == 0)) { obj.SendCommandEndResponse(0, 0x05, dev, 0x24, 0x00); return -1; } + sectors = (obj.cdrom.size >> 11) - 1; // Number 2048 byte blocks + break; + default: + if (obj.debug) console.log("SCSI Internal error 4", dev); + return -1; + } + + obj.SendDataToHost(dev, true, Buffer.concat([ IntToStr(8), new Buffer([0x00, 0x00, 0x0b, 0x40, 0x02, 0x00, 0x02, 0x00]) ]), featureRegister & 1); + break; + case 0x25: // READ_CAPACITY + if (obj.debug) console.log("SCSI: READ_CAPACITY", dev); + var len = 0; + switch(dev) + { + case 0xA0: // DEV_FLOPPY + if ((obj.floppy == null) || (obj.floppy.size == 0)) { obj.SendCommandEndResponse(0, 0x02, dev, 0x3a, 0x00); return -1; } + if (obj.floppy != null) { len = (obj.floppy.size >> 9) - 1; } + if (obj.debug) console.log('DEV_FLOPPY', len); // Number 512 byte blocks + break; + case 0xB0: // DEV_CDDVD + if ((obj.cdrom == null) || (obj.cdrom.size == 0)) { obj.SendCommandEndResponse(0, 0x02, dev, 0x3a, 0x00); return -1; } + if (obj.cdrom != null) { len = (obj.cdrom.size >> 11) - 1; } // Number 2048 byte blocks + if (obj.debug) console.log('DEV_CDDVD', len); + break; + default: + if (obj.debug) console.log("SCSI Internal error 4", dev); + return -1; + } + //if (dev == 0xA0) { dev = 0x00; } else { dev = 0x10; } // Weird but seems to work. + if (obj.debug) console.log("SCSI: READ_CAPACITY2", dev, deviceFlags); + obj.SendDataToHost(deviceFlags, true, Buffer.concat([IntToStr(len), new Buffer([0, 0, ((dev == 0xB0) ? 0x08 : 0x02), 0])]), featureRegister & 1); + break; + case 0x28: // READ_10 + lba = ReadInt(cdb, 2); + len = ReadShort(cdb, 7); + if (obj.debug) console.log("SCSI: READ_10", dev, lba, len); + sendDiskData(dev, lba, len, featureRegister); + break; + case 0x2a: // WRITE_10 (Floppy only) + case 0x2e: // WRITE_AND_VERIFY (Floppy only) + lba = ReadInt(cdb, 2); + len = ReadShort(cdb, 7); + if (obj.debug) console.log("SCSI: WRITE_10", dev, lba, len); + obj.SendGetDataFromHost(dev, 512 * len); // Floppy writes only, accept sectors of 512 bytes + break; + case 0x43: // READ_TOC (CD Audio only) + var buflen = ReadShort(cdb, 7); + var msf = cdb[1] & 0x02; + var format = cdb[2] & 0x07; + if (format == 0) { format = cdb[9] >> 6; } + if (obj.debug) console.log("SCSI: READ_TOC, dev=" + dev + ", buflen=" + buflen + ", msf=" + msf + ", format=" + format); + + switch (dev) { + case 0xA0: // DEV_FLOPPY + obj.SendCommandEndResponse(1, 0x05, dev, 0x20, 0x00); // Not implemented + return -1; + case 0xB0: // DEV_CDDVD + // NOP + break; + default: + if (obj.debug) console.log("SCSI Internal error 9", dev); + return -1; + } + + if (format == 1) { obj.SendDataToHost(dev, true, new Buffer([0x00, 0x0a, 0x01, 0x01, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]), featureRegister & 1); } + else if (format == 0) { + if (msf) { + obj.SendDataToHost(dev, true, new Buffer([0x00, 0x12, 0x01, 0x01, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0xaa, 0x00, 0x00, 0x00, 0x34, 0x13]), featureRegister & 1); + } else { + obj.SendDataToHost(dev, true, new Buffer([0x00, 0x12, 0x01, 0x01, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00]), featureRegister & 1); + } + } + break; + case 0x46: // GET_CONFIGURATION + var sendall = (cdb[1] != 2); + var firstcode = ReadShort(cdb, 2); + var buflen = ReadShort(cdb, 7); + + if (obj.debug) console.log("SCSI: GET_CONFIGURATION", dev, sendall, firstcode, buflen); + if (buflen == 0) { obj.SendDataToHost(dev, true, Buffer.concat([IntToStr(0x003c), IntToStr(0x0008)]), featureRegister & 1); return -1; } // TODO: Fixed this return, it's not correct. + + // Set the header + var r = null; + + // Add the data + if (firstcode == 0) { r = IDE_CD_ConfigArrayProfileList; } + if ((firstcode == 0x1) || (sendall && (firstcode < 0x1))) { r = IDE_CD_ConfigArrayCore; } + if ((firstcode == 0x2) || (sendall && (firstcode < 0x2))) { r = IDE_CD_Morphing; } + if ((firstcode == 0x3) || (sendall && (firstcode < 0x3))) { r = IDE_CD_ConfigArrayRemovable; } + if ((firstcode == 0x10) || (sendall && (firstcode < 0x10))) { r = IDE_CD_ConfigArrayRandom; } + if ((firstcode == 0x1E) || (sendall && (firstcode < 0x1E))) { r = IDE_CD_Read; } + if ((firstcode == 0x100) || (sendall && (firstcode < 0x100))) { r = IDE_CD_PowerManagement; } + if ((firstcode == 0x105) || (sendall && (firstcode < 0x105))) { r = IDE_CD_Timeout; } + + if (r == null) { + //console.log('NOT RIGHT', sendall, firstcode, cdb[2], cdb[3]); + //process.exit(0); + r = Buffer.concat([IntToStr(0x0008), IntToStr(4)]); + } else { + r = Buffer.concat([IntToStr(0x0008), IntToStr(r.length + 4), r]); + } + + // Cut the length to buflen if needed + if (r.length > buflen) { r = r.slice(0, buflen); } + + obj.SendDataToHost(dev, true, r, featureRegister & 1); + return -1; + case 0x4a: // GET_EV_STATUS - GET_EVENT_STATUS_NOTIFICATION + //var buflen = (cdb[7] << 8) + cdb[8]; + //if (buflen == 0) { obj.SendDataToHost(dev, true, Buffer.concat([IntToStr(0x003c), IntToStr(0x0008)]), featureRegister & 1); return -1; } // TODO: Fixed this return, it's not correct. + if (obj.debug) console.log("SCSI: GET_EVENT_STATUS_NOTIFICATION", dev, cdb[1], cdb[4], cdb[9]); + if ((cdb[1] != 0x01) && (cdb[4] != 0x10)) { + if (obj.debug) console.log('SCSI ERROR'); + obj.SendCommandEndResponse(1, 0x05, dev, 0x26, 0x01); + break; + } + var present = 0x00; + if ((dev == 0xA0) && (obj.floppy != null)) { present = 0x02; } + else if ((dev == 0xB0) && (obj.cdrom != null)) { present = 0x02; } + obj.SendDataToHost(dev, true, new Buffer([0x00, present, 0x80, 0x00]), featureRegister & 1); // This is the original version, 4 bytes long + break; + case 0x4c: + obj.SendCommand(0x51, Buffer.concat([ IntToStrX(0), IntToStrX(0), IntToStrX(0), new Buffer([0x87, 0x50, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x51, 0x05, 0x20, 0x00]) ]), true); + break; + case 0x51: // READ_DISC_INFO + if (obj.debug) console.log("SCSI READ_DISC_INFO", dev); + obj.SendCommandEndResponse(0, 0x05, dev, 0x20, 0x00); // Correct + return -1; + case 0x55: // MODE_SELECT_10: + if (obj.debug) console.log("SCSI ERROR: MODE_SELECT_10", dev); + obj.SendCommandEndResponse(1, 0x05, dev, 0x20, 0x00); + return -1; + case 0x5a: // MODE_SENSE_10 + if (obj.debug) console.log("SCSI: MODE_SENSE_10", dev, cdb[2] & 0x3f); + var buflen = ReadShort(cdb, 7); + //var pc = cdb[2] & 0xc0; + var r = null; + + if (buflen == 0) { obj.SendDataToHost(dev, true, Buffer.concat([IntToStr(0x003c), IntToStr(0x0008)]), featureRegister & 1); return -1; } // TODO: Fixed this return, it's not correct. + + // 1.44 mb floppy or LS120 (sectorCount == 0x3c300) + var sectorCount = 0; + if (dev == 0xA0) { + if (obj.floppy != null) { sectorCount = (obj.floppy.size >> 9); } + } else { + if (obj.cdrom != null) { sectorCount = (obj.cdrom.size >> 11); } + } + + switch (cdb[2] & 0x3f) { + case 0x01: if (dev == 0xA0) { r = (sectorCount <= 0xb40)?IDE_ModeSence_FloppyError_Recovery_Array:IDE_ModeSence_Ls120Error_Recovery_Array; } else { r = IDE_ModeSence_CDError_Recovery_Array; } break; + case 0x05: if (dev == 0xA0) { r = (sectorCount <= 0xb40)?IDE_ModeSence_FloppyDisk_Page_Array:IDE_ModeSence_LS120Disk_Page_Array; } break; + case 0x3f: if (dev == 0xA0) { r = (sectorCount <= 0xb40)?IDE_ModeSence_3F_Floppy_Array:IDE_ModeSence_3F_LS120_Array; } else { r = IDE_ModeSence_3F_CD_Array; } break; + case 0x1A: if (dev == 0xB0) { r = IDE_ModeSence_CD_1A_Array; } break; + case 0x1D: if (dev == 0xB0) { r = IDE_ModeSence_CD_1D_Array; } break; + case 0x2A: if (dev == 0xB0) { r = IDE_ModeSence_CD_2A_Array; } break; + } + + if (r == null) { + obj.SendCommandEndResponse(0, 0x05, dev, 0x20, 0x00); // TODO: Send proper error!!! + } else { + // Set disk to read only (we don't support write). + //ms_data[3] = ms_data[3] | 0x80; + obj.SendDataToHost(dev, true, r, featureRegister & 1); + } + break; + default: // UNKNOWN COMMAND + if (obj.debug) console.log("IDER: Unknown SCSI command", cdb[0]); + obj.SendCommandEndResponse(0, 0x05, dev, 0x20, 0x00); + return -1; + } + return 0; + } + + function sendDiskData(dev, lba, len, featureRegister) { + var media = null; + var mediaBlocks = 0; + if (dev == 0xA0) { media = obj.floppy; if (obj.floppy != null) { mediaBlocks = (obj.floppy.size >> 9); } } + if (dev == 0xB0) { media = obj.cdrom; if (obj.cdrom != null) { mediaBlocks = (obj.cdrom.size >> 11); } } + if ((len < 0) || (lba + len > mediaBlocks)) { obj.SendCommandEndResponse(1, 0x05, dev, 0x21, 0x00); return 0; } + if (len == 0) { obj.SendCommandEndResponse(1, 0x00, dev, 0x00, 0x00); return 0; } + if (media != null) { + // Send sector stats + if (obj.sectorStats) { obj.sectorStats(1, (dev == 0xA0) ? 0 : 1, mediaBlocks, lba, len); } + if (dev == 0xA0) { lba <<= 9; len <<= 9; } else { lba <<= 11; len <<= 11; } + if (g_media !== null) { + // Queue read operation + g_readQueue.push({ media: media, dev: dev, lba: lba, len: len, fr: featureRegister }); + } else { + // obj.iderinfo.readbfr // TODO: MaxRead + g_media = media; + g_dev = dev; + g_lba = lba; + g_len = len; + sendDiskDataEx(featureRegister); + } + } + } + + var g_readQueue = []; + var g_reset = false; + var g_media = null; + var g_dev; + var g_lba; + var g_len; + function sendDiskDataEx(featureRegister) { + var len = g_len, lba = g_lba; + if (g_len > obj.iderinfo.readbfr) { len = obj.iderinfo.readbfr; } + g_len -= len; + g_lba += len; + + //console.log('Read from ' + lba + ' to ' + (lba + len) + ', total of ' + len); + + var result = new Buffer(len); + fs.readSync(g_media.file, result, 0, len, lba); + obj.SendDataToHost(g_dev, (g_len == 0), result, featureRegister & 1); + if ((g_len > 0) && (g_reset == false)) { + sendDiskDataEx(featureRegister); + } else { + g_media = null; + if (g_reset) { obj.SendCommand(0x47); g_readQueue = []; g_reset = false; } // Send ResetOccuredResponse + else if (g_readQueue.length > 0) { var op = g_readQueue.shift(); g_media = op.media; g_dev = op.dev; g_lba = op.lba; g_len = op.len; sendDiskDataEx(op.fr); } // Un-queue read operation + } + } + + return obj; +} + +function ShortToStr(v) { return new Buffer([(v >> 8) & 0xFF, v & 0xFF]); } +function ShortToStrX(v) { return new Buffer([v & 0xFF, (v >> 8) & 0xFF]); } +function IntToStr(v) { return new Buffer([(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]); } +function IntToStrX(v) { return new Buffer([v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF]); } +function ReadShort(v, p) { return (v[p] << 8) + v[p + 1]; } +function ReadShortX(v, p) { return (v[p + 1] << 8) + v[p]; } +function ReadInt(v, p) { return (v[p] * 0x1000000) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; } // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32. +function ReadSInt(v, p) { return (v[p] << 24) + (v[p + 1] << 16) + (v[p + 2] << 8) + v[p + 3]; } +function ReadIntX(v, p) { return (v[p + 3] * 0x1000000) + (v[p + 2] << 16) + (v[p + 1] << 8) + v[p]; } \ No newline at end of file diff --git a/agents/modules_meshcmd/amt-redir-duk.js b/agents/modules_meshcmd/amt-redir-duk.js new file mode 100644 index 00000000..a8a252d4 --- /dev/null +++ b/agents/modules_meshcmd/amt-redir-duk.js @@ -0,0 +1,308 @@ +/** +* @description Intel AMT Redirection Transport Module - using Node +* @author Ylian Saint-Hilaire +* @version v0.0.1f +*/ + +// Construct a MeshServer object +module.exports = function CreateAmtRedirect(module) { + var obj = {}; + obj.m = module; // This is the inner module (Terminal or Desktop) + module.parent = obj; + obj.State = 0; + obj.net = require('net'); + obj.tls = require('tls'); + obj.socket = null; + obj.host = null; + obj.port = 0; + obj.user = null; + obj.pass = null; + obj.connectstate = 0; + obj.protocol = module.protocol; // 1 = SOL, 2 = KVM, 3 = IDER + obj.xtlsoptions = null; + + obj.amtaccumulator = null; + obj.amtsequence = 1; + obj.amtkeepalivetimer = null; + obj.authuri = "/RedirectionService"; + obj.digestRealmMatch = null; + + obj.onStateChanged = null; + + // Private method + obj.Debug = function (msg) { console.log(msg); } + var urlvars = null; + + obj.Start = function (host, port, user, pass, tls, tlsFingerprint, tlsoptions) { + obj.host = host; + obj.port = port; + obj.user = user; + obj.pass = pass; + obj.xtls = tls; + obj.xtlsoptions = tlsoptions; + obj.xtlsFingerprint = tlsFingerprint; + obj.connectstate = 0; + + if (tls == true) { + obj.socket = obj.tls.connect({ host: host, port: port, rejectUnauthorized: false, checkServerIdentity: obj.onCheckServerIdentity }, obj.xxOnSocketConnected); + } else { + obj.socket = obj.net.createConnection({ host: host, port: port }, obj.xxOnSocketConnected); + } + obj.socket.on('data', obj.xxOnSocketData); + obj.socket.on('close', obj.xxOnSocketClosed); + obj.socket.on('error', obj.xxOnSocketClosed); + obj.xxStateChange(1); + } + + // Get the certificate of Intel AMT + //obj.getPeerCertificate = function () { if (obj.xtls == true) { return obj.socket.getPeerCertificate(); } return null; } + + obj.onCheckServerIdentity = function (cert) { + var f = cert[0].fingerprint.split(':').join('').toLowerCase(); + if ((obj.xtlsFingerprint != null) && (obj.xtlsFingerprint != f)) { + console.log('Invalid TLS Cert, SHA384: ' + f); + process.exit(2); + return; + } else { + if (obj.xtlsFingerprint == null) { + obj.xtlsFingerprint = f; + console.log('TLS Cert SHA384: ' + f); + } + } + } + + obj.xxOnSocketConnected = function () { + if (obj.socket == null) return; + /* + if (obj.xtls == true) { + obj.xtlsCertificate = obj.socket.getPeerCertificate(); + if ((obj.xtlsFingerprint != 0) && (obj.xtlsCertificate.fingerprint.split(':').join('').toLowerCase() != obj.xtlsFingerprint)) { obj.Stop(); return; } + } + */ + + if (urlvars && urlvars['redirtrace']) { console.log("REDIR-CONNECTED"); } + //obj.Debug("Socket Connected"); + obj.xxStateChange(2); + if (obj.protocol == 1) obj.xxSend(obj.RedirectStartSol); // TODO: Put these strings in higher level module to tighten code + else if (obj.protocol == 2) obj.xxSend(obj.RedirectStartKvm); // Don't need these is the feature if not compiled-in. + else if (obj.protocol == 3) obj.xxSend(obj.RedirectStartIder); + } + + obj.xxOnSocketData = function (data) { + //console.log('xxOnSocketData: ' + data.toString('hex'), data.length); + if (!data || obj.connectstate == -1) return; + if (urlvars && urlvars['redirtrace']) { console.log("REDIR-RECV(" + data.length + "): " + data.toString('hex')); } + //obj.Debug("Recv(" + data.length + "): " + rstr2hex(data)); + if ((obj.protocol == 2 || obj.protocol == 3) && obj.connectstate == 1) { return obj.m.ProcessData(data); } // KVM or IDER traffic, forward it directly. + if (obj.amtaccumulator == null) { obj.amtaccumulator = data; } else { obj.amtaccumulator = Buffer.concat(obj.amtaccumulator, data); } + //obj.Debug("Recv(" + obj.amtaccumulator.length + "): " + rstr2hex(obj.amtaccumulator)); + while (obj.amtaccumulator != null) { + var cmdsize = 0; + //console.log('CMD: ' + obj.amtaccumulator[0]); + switch (obj.amtaccumulator[0]) { + case 0x11: // StartRedirectionSessionReply (17) + if (obj.amtaccumulator.length < 4) return; + var statuscode = obj.amtaccumulator[1]; + switch (statuscode) { + case 0: // STATUS_SUCCESS + if (obj.amtaccumulator.length < 13) return; + var oemlen = obj.amtaccumulator[12]; + if (obj.amtaccumulator.length < 13 + oemlen) return; + obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); // Query authentication support + cmdsize = (13 + oemlen); + break; + default: + obj.Stop(); + break; + } + break; + case 0x14: // AuthenticateSessionReply (20) + if (obj.amtaccumulator.length < 9) return; + var authDataLen = obj.amtaccumulator.readInt32LE(5); + if (obj.amtaccumulator.length < 9 + authDataLen) return; + var status = obj.amtaccumulator[1]; + var authType = obj.amtaccumulator[4]; + var authData = []; + for (i = 0; i < authDataLen; i++) { authData.push(obj.amtaccumulator[9 + i]); } + var authDataBuf = obj.amtaccumulator.slice(9, 9 + authDataLen); + cmdsize = 9 + authDataLen; + if (authType == 0) { + // Query + if (authData.indexOf(4) >= 0) { + // Good Digest Auth (With cnonce and all) + obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x04) + IntToStrX(obj.user.length + obj.authuri.length + 8) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(0x00, 0x00) + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(0x00, 0x00, 0x00, 0x00)); + } + else if (authData.indexOf(3) >= 0) { + // Bad Digest Auth (Not sure why this is supported, cnonce is not used!) + obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x03) + IntToStrX(obj.user.length + obj.authuri.length + 7) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(0x00, 0x00) + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(0x00, 0x00, 0x00)); + } + else if (authData.indexOf(1) >= 0) { + // Basic Auth (Probably a good idea to not support this unless this is an old version of Intel AMT) + obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x01) + IntToStrX(obj.user.length + obj.pass.length + 2) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(obj.pass.length) + obj.pass); + } + else obj.Stop(); + } + else if ((authType == 3 || authType == 4) && status == 1) { + var curptr = 0; + + // Realm + var realmlen = authDataBuf[curptr]; + var realm = authDataBuf.slice(curptr + 1, curptr + 1 + realmlen).toString(); + curptr += (realmlen + 1); + + // Check the digest realm. If it does not match, close the connection. + if (obj.digestRealmMatch && (obj.digestRealmMatch != realm)) { obj.Stop(); return; } + + // Nonce + var noncelen = authDataBuf[curptr]; + var nonce = authDataBuf.slice(curptr + 1, curptr + 1 + noncelen).toString(); + curptr += (noncelen + 1); + + // QOP + var qoplen = 0; + var qop = null; + var cnonce = obj.xxRandomValueHex(32); + var snc = '00000002'; + var extra = ''; + if (authType == 4) { + qoplen = authDataBuf[curptr]; + qop = authDataBuf.slice(curptr + 1, curptr + 1 + qoplen).toString(); + curptr += (qoplen + 1); + extra = snc + ":" + cnonce + ":" + qop + ":"; + } + var digest = hex_md5(hex_md5(obj.user + ":" + realm + ":" + obj.pass) + ":" + nonce + ":" + extra + hex_md5("POST:" + obj.authuri)); + var totallen = obj.user.length + realm.length + nonce.length + obj.authuri.length + cnonce.length + snc.length + digest.length + 7; + if (authType == 4) totallen += (qop.length + 1); + var buf = Buffer.concat([new Buffer([0x13, 0x00, 0x00, 0x00, authType]), new Buffer([totallen & 0xFF, (totallen >> 8) & 0xFF, 0x00, 0x00]), new Buffer([obj.user.length]), new Buffer(obj.user), new Buffer([realm.length]), new Buffer(realm), new Buffer([nonce.length]), new Buffer(nonce), new Buffer([obj.authuri.length]), new Buffer(obj.authuri), new Buffer([cnonce.length]), new Buffer(cnonce), new Buffer([snc.length]), new Buffer(snc), new Buffer([digest.length]), new Buffer(digest)]); + if (authType == 4) buf = Buffer.concat([ buf, new Buffer([qop.length]), new Buffer(qop) ]); + obj.xxSend(buf); + } + else if (status == 0) { // Success + if (obj.protocol == 1) { + /* + // Serial-over-LAN: Send Intel AMT serial settings... + var MaxTxBuffer = 10000; + var TxTimeout = 100; + var TxOverflowTimeout = 0; + var RxTimeout = 10000; + var RxFlushTimeout = 100; + var Heartbeat = 0;//5000; + obj.xxSend(String.fromCharCode(0x20, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++) + ToShortStr(MaxTxBuffer) + ToShortStr(TxTimeout) + ToShortStr(TxOverflowTimeout) + ToShortStr(RxTimeout) + ToShortStr(RxFlushTimeout) + ToShortStr(Heartbeat) + ToIntStr(0)); + */ + } + if (obj.protocol == 2) { + // Remote Desktop: Send traffic directly... + obj.xxSend(new Buffer([0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); + } + if (obj.protocol == 3) { + // Remote IDER: Send traffic directly... + obj.connectstate = 1; + obj.xxStateChange(3); + } + } else obj.Stop(); + break; + case 0x21: // Response to settings (33) + if (obj.amtaccumulator.length < 23) break; + cmdsize = 23; + obj.xxSend(String.fromCharCode(0x27, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++) + String.fromCharCode(0x00, 0x00, 0x1B, 0x00, 0x00, 0x00)); + if (obj.protocol == 1) { obj.amtkeepalivetimer = setInterval(obj.xxSendAmtKeepAlive, 2000); } + obj.connectstate = 1; + obj.xxStateChange(3); + break; + case 0x29: // Serial Settings (41) + if (obj.amtaccumulator.length < 10) break; + cmdsize = 10; + break; + case 0x2A: // Incoming display data (42) + if (obj.amtaccumulator.length < 10) break; + var cs = (10 + ((obj.amtaccumulator[9] & 0xFF) << 8) + (obj.amtaccumulator[8] & 0xFF)); + if (obj.amtaccumulator.length < cs) break; + obj.m.ProcessData(obj.amtaccumulator.substring(10, cs)); + cmdsize = cs; + break; + case 0x2B: // Keep alive message (43) + if (obj.amtaccumulator.length < 8) break; + cmdsize = 8; + break; + case 0x41: + if (obj.amtaccumulator.length < 8) break; + obj.connectstate = 1; + obj.m.Start(); + // KVM traffic, forward rest of accumulator directly. + if (obj.amtaccumulator.length > 8) { obj.m.ProcessData(obj.amtaccumulator.substring(8)); } + cmdsize = obj.amtaccumulator.length; + break; + default: + console.log("Unknown Intel AMT command: " + obj.amtaccumulator[0] + " acclen=" + obj.amtaccumulator.length); + obj.Stop(); + return; + } + if (cmdsize == 0) return; + if (cmdsize == obj.amtaccumulator.length) { obj.amtaccumulator = null; } else { obj.amtaccumulator = obj.amtaccumulator.slice(cmdsize); } + } + } + + obj.xxSend = function (x) { + if (urlvars && urlvars['redirtrace']) { console.log("REDIR-SEND(" + x.length + "): " + rstr2hex(x)); } + //obj.Debug("Send(" + x.length + "): " + new Buffer(x, "binary").toString('hex')); + if (typeof x == 'string') { obj.socket.write(new Buffer(x, "binary")); } else { obj.socket.write(x); } + } + + obj.Send = function (x) { + if (obj.socket == null || obj.connectstate != 1) return; + if (obj.protocol == 1) { obj.xxSend(String.fromCharCode(0x28, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++) + ToShortStr(x.length) + x); } else { obj.xxSend(x); } + } + + obj.xxSendAmtKeepAlive = function () { + if (obj.socket == null) return; + obj.xxSend(String.fromCharCode(0x2B, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++)); + } + + // Uses OpenSSL random to generate a hex string + obj.xxRandomValueHex = function (len) { + var t = [], l = Math.floor(len / 2); + for (var i = 0; i < l; i++) { t.push(obj.tls.generateRandomInteger("0", "255")); } + return new Buffer(t).toString('hex'); + } + + obj.xxOnSocketClosed = function () { + obj.socket = null; + if (urlvars && urlvars['redirtrace']) { console.log("REDIR-CLOSED"); } + //obj.Debug("Socket Closed"); + obj.Stop(); + } + + obj.xxStateChange = function(newstate) { + if (obj.State == newstate) return; + obj.State = newstate; + obj.m.xxStateChange(obj.State); + if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State); + } + + obj.Stop = function () { + if (urlvars && urlvars['redirtrace']) { console.log("REDIR-CLOSED"); } + //obj.Debug("Socket Stopped"); + obj.xxStateChange(0); + obj.connectstate = -1; + obj.amtaccumulator = ""; + if (obj.socket != null) { obj.socket.destroy(); obj.socket = null; } + if (obj.amtkeepalivetimer != null) { clearInterval(obj.amtkeepalivetimer); obj.amtkeepalivetimer = null; } + } + + obj.RedirectStartSol = new Buffer([0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20]); + obj.RedirectStartKvm = new Buffer([0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52]); + obj.RedirectStartIder = new Buffer([0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52]); + + return obj; +} + +function ToIntStr(v) { return String.fromCharCode((v & 0xFF), ((v >> 8) & 0xFF), ((v >> 16) & 0xFF), ((v >> 24) & 0xFF)); } +function ToShortStr(v) { return String.fromCharCode((v & 0xFF), ((v >> 8) & 0xFF)); } + +function ShortToStr(v) { return String.fromCharCode((v >> 8) & 0xFF, v & 0xFF); } +function ShortToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF); } +function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); } +function IntToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); } + +var md5hasher = require('MD5Stream').create(); +function hex_md5(a) { return md5hasher.syncHash(a).toString('hex').toLowerCase(); } \ No newline at end of file diff --git a/agents/modules_meshcmd_min/amt-ider.min.js b/agents/modules_meshcmd_min/amt-ider.min.js new file mode 100644 index 00000000..fe99b6e2 --- /dev/null +++ b/agents/modules_meshcmd_min/amt-ider.min.js @@ -0,0 +1 @@ +module.exports=function CreateAmtRemoteIder(){var B={};B.protocol=3;B.bytesToAmt=0;B.bytesFromAmt=0;B.rx_timeout=30000;B.tx_timeout=0;B.heartbeat=20000;B.version=1;B.acc=null;B.inSequence=0;B.outSequence=0;B.iderinfo=null;B.enabled=false;B.iderStart=0;B.floppy=null;B.cdrom=null;B.floppyReady=false;B.cdromReady=false;B.sectorStats=null;B.debug=false;var z=new Buffer([0,38,49,128,0,0,0,0,5,30,16,169,8,32,2,0,3,195,0,0,0,0,0,0,0,0,0,0,40,0,0,0,0,0,0,0,2,208,0,0]);var s=new Buffer([0,92,36,128,0,0,0,0,1,10,0,1,0,0,0,0,2,0,0,0,3,22,0,160,0,0,0,0,0,18,2,0,0,0,0,0,0,0,160,0,0,0,5,30,16,169,8,32,2,0,3,195,0,0,0,0,0,0,0,0,0,0,40,0,0,0,0,0,0,0,2,208,0,0,8,10,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,17,36,49]);var x=new Buffer([0,38,36,128,0,0,0,0,5,30,4,176,2,18,2,0,0,80,0,0,0,0,0,0,0,0,0,0,40,0,0,0,0,0,0,0,2,208,0,0]);var r=new Buffer([0,92,36,128,0,0,0,0,1,10,0,1,0,0,0,0,2,0,0,0,3,22,0,160,0,0,0,0,0,18,2,0,0,0,0,0,0,0,160,0,0,0,5,30,4,176,2,18,2,0,0,80,0,0,0,0,0,0,0,0,0,0,40,0,0,0,0,0,0,0,2,208,0,0,8,10,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,17,36,49]);var t=new Buffer([0,18,1,128,0,0,0,0,26,10,0,0,0,0,0,0,0,0,0,0]);var u=new Buffer([0,18,1,128,0,0,0,0,29,10,0,0,0,0,0,0,0,0,0,0]);var v=new Buffer([0,32,1,128,0,0,0,0,42,24,0,0,0,0,32,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0]);var q=new Buffer([0,40,1,128,0,0,0,0,1,6,0,255,0,0,0,0,42,24,0,0,0,0,2,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0]);var i=new Buffer([0,0,0,40,0,0,0,8]);var j=new Buffer([0,0,3,4,0,8,1,0]);var h=new Buffer([0,1,3,4,0,0,0,2]);var m=new Buffer([0,2,3,4,0,0,0,0]);var l=new Buffer([0,3,3,4,41,0,0,2]);var k=new Buffer([0,16,1,8,0,0,8,0,0,1,0,0]);var o=new Buffer([0,30,3,0]);var n=new Buffer([1,0,3,0]);var p=new Buffer([1,5,3,0]);var y=new Buffer([0,18,36,128,0,0,0,0,1,10,0,1,0,0,0,0,2,0,0,0]);var A=new Buffer([0,18,49,128,0,0,0,0,1,10,0,1,0,0,0,0,2,0,0,0]);var w=new Buffer([0,14,1,128,0,0,0,0,1,6,0,255,0,0,0,0]);B.xxStateChange=function(E){if(B.debug){console.log("IDER-StateChange",E)}if(E==0){B.Stop()}if(E==3){B.Start()}};B.Start=function(){if(B.debug){console.log("IDER-Start");console.log(B.floppy,B.cdrom)}B.bytesToAmt=0;B.bytesFromAmt=0;B.inSequence=0;B.outSequence=0;e=[];B.SendCommand(64,Buffer.concat([ShortToStrX(B.rx_timeout),ShortToStrX(B.tx_timeout),ShortToStrX(B.heartbeat),IntToStrX(B.version)]));if(B.sectorStats){B.sectorStats(0,0,B.floppy?(B.floppy.size>>9):0);B.sectorStats(0,1,B.cdrom?(B.cdrom.size>>11):0)}};B.Stop=function(){if(B.debug){console.log("IDER-Stop")}B.parent.Stop()};B.ProcessData=function(E){B.bytesFromAmt+=E.length;if(B.acc==null){B.acc=E}else{B.acc=Buffer.concat(B.acc,E)}if(B.debug){console.log("IDER-ProcessData",B.acc.length,B.acc.toString("hex"))}while(B.acc!=null){var F=B.ProcessDataEx();if(F==0){return}if(B.inSequence!=ReadIntX(B.acc,4)){if(B.debug){console.log("ERROR: Out of sequence",B.inSequence,ReadIntX(B.acc,4))}B.Stop();return}B.inSequence++;if(F==B.acc.length){B.acc=null}else{B.acc=B.acc.slice(F)}}};B.SendCommand=function(F,H,G,I){if(H==null){H=new Buffer(0)}var E=((F>50)&&(G==true))?2:0;if(I){E+=1}var J=Buffer.concat([Buffer([F,0,0,E]),IntToStrX(B.outSequence++),H]);B.parent.xxSend(J);B.bytesToAmt+=J.length};B.SendCommandEndResponse=function(H,I,G,E,F){if(H){B.SendCommand(81,new Buffer([0,0,0,0,0,0,0,0,0,0,0,0,197,0,3,0,0,0,G,80,0,0,0]),true)}else{B.SendCommand(81,new Buffer([0,0,0,0,0,0,0,0,0,0,0,0,135,(I<<4),3,0,0,0,G,81,I,E,F]),true)}};B.SendDataToHost=function(G,E,F,H){var I=(H)?0:F.length;if(E==true){B.SendCommand(84,Buffer.concat([new Buffer([0,(F.length&255),(F.length>>8),0,H?180:181,0,2,0,(I&255),(I>>8),G,88,133,0,3,0,0,0,G,80,0,0,0,0,0,0]),F]),E,H)}else{B.SendCommand(84,Buffer.concat([new Buffer([0,(F.length&255),(F.length>>8),0,H?180:181,0,2,0,(I&255),(I>>8),G,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),F]),E,H)}};B.SendGetDataFromHost=function(F,E){B.SendCommand(82,new Buffer([0,(E&255),(E>>8),0,181,0,0,0,(E&255),(E>>8),F,88,0,0,0,0,0,0,0,0,0,0,0]),false)};B.SendDisableEnableFeatures=function(F,E){if(E==null){E=""}B.SendCommand(72,Buffer.concat([new Buffer([F]),E]))};B.ProcessDataEx=function(){if(B.acc.length<8){return 0}switch(B.acc[0]){case 65:if(B.acc.length<30){return 0}var I=B.acc[29];if(B.acc.length<(30+I)){return 0}B.iderinfo={};B.iderinfo.major=B.acc[8];B.iderinfo.minor=B.acc[9];B.iderinfo.fwmajor=B.acc[10];B.iderinfo.fwminor=B.acc[11];B.iderinfo.readbfr=ReadShortX(B.acc,16);B.iderinfo.writebfr=ReadShortX(B.acc,18);B.iderinfo.proto=B.acc[21];B.iderinfo.iana=ReadIntX(B.acc,25);if(B.debug){console.log(B.iderinfo)}if(B.iderinfo.proto!=0){if(B.debug){console.log("Unknown proto",B.iderinfo.proto)}B.Stop()}if(B.iderinfo.readbfr>8192){if(B.debug){console.log("Illegal read buffer size",B.iderinfo.readbfr)}B.Stop()}if(B.iderinfo.writebfr>8192){if(B.debug){console.log("Illegal write buffer size",B.iderinfo.writebfr)}B.Stop()}if(B.iderStart==0){B.SendDisableEnableFeatures(3,IntToStrX(1+8))}else{if(B.iderStart==1){B.SendDisableEnableFeatures(3,IntToStrX(1+16))}else{if(B.iderStart==2){B.SendDisableEnableFeatures(3,IntToStrX(1+24))}}}return 30+I;case 67:if(B.debug){console.log("CLOSE")}B.Stop();return 8;case 68:B.SendCommand(69);return 8;case 69:if(B.debug){console.log("PONG")}return 8;case 70:if(B.acc.length<9){return 0}var J=B.acc[8];if(d===null){B.SendCommand(71);if(B.debug){console.log("RESETOCCURED1",J)}}else{f=true;if(B.debug){console.log("RESETOCCURED2",J)}}return 9;case 73:if(B.acc.length<13){return 0}var K=B.acc[8];var L=ReadIntX(B.acc,9);if(B.debug){console.log("STATUS_DATA",K,L)}switch(K){case 1:if(L&1){if(B.iderStart==0){B.SendDisableEnableFeatures(3,IntToStrX(1+8))}else{if(B.iderStart==1){B.SendDisableEnableFeatures(3,IntToStrX(1+16))}else{if(B.iderStart==2){B.SendDisableEnableFeatures(3,IntToStrX(1+24))}}}}break;case 2:B.enabled=(L&2)?true:false;if(B.debug){console.log("IDER Status: "+B.enabled)}break;case 3:if(L!=1){if(B.debug){console.log("Register toggle failure")}}break}return 13;case 74:if(B.acc.length<11){return 0}if(B.debug){console.log("IDER: ABORT",B.acc[8])}return 11;case 75:return 8;case 80:if(B.acc.length<28){return 0}var F=(B.acc[14]&16)?176:160;var G=B.acc[14];var E=B.acc.slice(16,28);var H=B.acc[9];if(B.debug){console.log("SCSI_CMD",F,E.toString("hex"),H,G)}g(F,E,H,G);return 28;case 83:if(B.acc.length<14){return 0}var I=ReadShortX(B.acc,9);if(B.acc.length<(14+I)){return 0}if(B.debug){console.log("SCSI_WRITE, len = "+(14+I))}B.SendCommand(81,new Buffer([0,0,0,0,0,0,0,0,0,0,0,0,135,112,3,0,0,0,160,81,7,39,0]),true);return 14+I;default:if(B.debug){console.log("Unknown IDER command",B.acc[0])}B.Stop();break}return 0};function g(I,H,K,J){var N;var O;switch(H[0]){case 0:if(B.debug){console.log("SCSI: TEST_UNIT_READY",I)}switch(I){case 160:if(B.floppy==null){B.SendCommandEndResponse(1,2,I,58,0);return -1}if(B.floppyReady==false){B.floppyReady=true;B.SendCommandEndResponse(1,6,I,40,0);return -1}break;case 176:if(B.cdrom==null){B.SendCommandEndResponse(1,2,I,58,0);return -1}if(B.cdromReady==false){B.cdromReady=true;B.SendCommandEndResponse(1,6,I,40,0);return -1}break;default:if(B.debug){console.log("SCSI Internal error 3",I)}return -1}B.SendCommandEndResponse(1,0,I,0,0);break;case 8:N=((H[1]&31)<<16)+(H[2]<<8)+H[3];O=H[4];if(O==0){O=256}if(B.debug){console.log("SCSI: READ_6",I,N,O)}C(I,N,O,K);break;case 10:N=((H[1]&31)<<16)+(H[2]<<8)+H[3];O=H[4];if(O==0){O=256}if(B.debug){console.log("SCSI: WRITE_6",I,N,O)}B.SendCommandEndResponse(1,2,I,58,0);return -1;case 26:if(B.debug){console.log("SCSI: MODE_SENSE_6",I)}if((H[2]==63)&&(H[3]==0)){var E=0,F=0;switch(I){case 160:if(B.floppy==null){B.SendCommandEndResponse(1,2,I,58,0);return -1}E=0;F=128;break;case 176:if(B.cdrom==null){B.SendCommandEndResponse(1,2,I,58,0);return -1}E=5;F=128;break;default:if(B.debug){console.log("SCSI Internal error 6",I)}return -1}B.SendDataToHost(I,true,new Buffer([0,E,F,0]),K&1);return}B.SendCommandEndResponse(1,5,I,36,0);break;case 27:B.SendCommandEndResponse(1,0,I);break;case 30:if(B.debug){console.log("SCSI: ALLOW_MEDIUM_REMOVAL",I)}if((I==160)&&(B.floppy==null)){B.SendCommandEndResponse(1,2,I,58,0);return -1}if((I==176)&&(B.cdrom==null)){B.SendCommandEndResponse(1,2,I,58,0);return -1}B.SendCommandEndResponse(1,0,I,0,0);break;case 35:if(B.debug){console.log("SCSI: READ_FORMAT_CAPACITIES",I)}var G=ReadShort(H,7);var Q=0,V;var P=G/8;switch(I){case 160:if((B.floppy==null)||(B.floppy.size==0)){B.SendCommandEndResponse(0,5,I,36,0);return -1}V=(B.floppy.size>>9)-1;break;case 176:if((B.cdrom==null)||(B.cdrom.size==0)){B.SendCommandEndResponse(0,5,I,36,0);return -1}V=(B.cdrom.size>>11)-1;break;default:if(B.debug){console.log("SCSI Internal error 4",I)}return -1}B.SendDataToHost(I,true,Buffer.concat([IntToStr(8),new Buffer([0,0,11,64,2,0,2,0])]),K&1);break;case 37:if(B.debug){console.log("SCSI: READ_CAPACITY",I)}var O=0;switch(I){case 160:if((B.floppy==null)||(B.floppy.size==0)){B.SendCommandEndResponse(0,2,I,58,0);return -1}if(B.floppy!=null){O=(B.floppy.size>>9)-1}if(B.debug){console.log("DEV_FLOPPY",O)}break;case 176:if((B.cdrom==null)||(B.cdrom.size==0)){B.SendCommandEndResponse(0,2,I,58,0);return -1}if(B.cdrom!=null){O=(B.cdrom.size>>11)-1}if(B.debug){console.log("DEV_CDDVD",O)}break;default:if(B.debug){console.log("SCSI Internal error 4",I)}return -1}if(B.debug){console.log("SCSI: READ_CAPACITY2",I,J)}B.SendDataToHost(J,true,Buffer.concat([IntToStr(O),new Buffer([0,0,((I==176)?8:2),0])]),K&1);break;case 40:N=ReadInt(H,2);O=ReadShort(H,7);if(B.debug){console.log("SCSI: READ_10",I,N,O)}C(I,N,O,K);break;case 42:case 46:N=ReadInt(H,2);O=ReadShort(H,7);if(B.debug){console.log("SCSI: WRITE_10",I,N,O)}B.SendGetDataFromHost(I,512*O);break;case 67:var G=ReadShort(H,7);var R=H[1]&2;var M=H[2]&7;if(M==0){M=H[9]>>6}if(B.debug){console.log("SCSI: READ_TOC, dev="+I+", buflen="+G+", msf="+R+", format="+M)}switch(I){case 160:B.SendCommandEndResponse(1,5,I,32,0);return -1;case 176:break;default:if(B.debug){console.log("SCSI Internal error 9",I)}return -1}if(M==1){B.SendDataToHost(I,true,new Buffer([0,10,1,1,0,20,1,0,0,0,0,0]),K&1)}else{if(M==0){if(R){B.SendDataToHost(I,true,new Buffer([0,18,1,1,0,20,1,0,0,0,2,0,0,20,170,0,0,0,52,19]),K&1)}else{B.SendDataToHost(I,true,new Buffer([0,18,1,1,0,20,1,0,0,0,0,0,0,20,170,0,0,0,0,0]),K&1)}}}break;case 70:var W=(H[1]!=2);var L=ReadShort(H,2);var G=ReadShort(H,7);if(B.debug){console.log("SCSI: GET_CONFIGURATION",I,W,L,G)}if(G==0){B.SendDataToHost(I,true,Buffer.concat([IntToStr(60),IntToStr(8)]),K&1);return -1}var T=null;if(L==0){T=j}if((L==1)||(W&&(L<1))){T=h}if((L==2)||(W&&(L<2))){T=m}if((L==3)||(W&&(L<3))){T=l}if((L==16)||(W&&(L<16))){T=k}if((L==30)||(W&&(L<30))){T=o}if((L==256)||(W&&(L<256))){T=n}if((L==261)||(W&&(L<261))){T=p}if(T==null){T=Buffer.concat([IntToStr(8),IntToStr(4)])}else{T=Buffer.concat([IntToStr(8),IntToStr(T.length+4),T])}if(T.length>G){T=T.slice(0,G)}B.SendDataToHost(I,true,T,K&1);return -1;case 74:if(B.debug){console.log("SCSI: GET_EVENT_STATUS_NOTIFICATION",I,H[1],H[4],H[9])}if((H[1]!=1)&&(H[4]!=16)){if(B.debug){console.log("SCSI ERROR")}B.SendCommandEndResponse(1,5,I,38,1);break}var S=0;if((I==160)&&(B.floppy!=null)){S=2}else{if((I==176)&&(B.cdrom!=null)){S=2}}B.SendDataToHost(I,true,new Buffer([0,S,128,0]),K&1);break;case 76:B.SendCommand(81,Buffer.concat([IntToStrX(0),IntToStrX(0),IntToStrX(0),new Buffer([135,80,3,0,0,0,176,81,5,32,0])]),true);break;case 81:if(B.debug){console.log("SCSI READ_DISC_INFO",I)}B.SendCommandEndResponse(0,5,I,32,0);return -1;case 85:if(B.debug){console.log("SCSI ERROR: MODE_SELECT_10",I)}B.SendCommandEndResponse(1,5,I,32,0);return -1;case 90:if(B.debug){console.log("SCSI: MODE_SENSE_10",I,H[2]&63)}var G=ReadShort(H,7);var T=null;if(G==0){B.SendDataToHost(I,true,Buffer.concat([IntToStr(60),IntToStr(8)]),K&1);return -1}var U=0;if(I==160){if(B.floppy!=null){U=(B.floppy.size>>9)}}else{if(B.cdrom!=null){U=(B.cdrom.size>>11)}}switch(H[2]&63){case 1:if(I==160){T=(U<=2880)?y:A}else{T=w}break;case 5:if(I==160){T=(U<=2880)?x:z}break;case 63:if(I==160){T=(U<=2880)?r:s}else{T=q}break;case 26:if(I==176){T=t}break;case 29:if(I==176){T=u}break;case 42:if(I==176){T=v}break}if(T==null){B.SendCommandEndResponse(0,5,I,32,0)}else{B.SendDataToHost(I,true,T,K&1)}break;default:if(B.debug){console.log("IDER: Unknown SCSI command",H[0])}B.SendCommandEndResponse(0,5,I,32,0);return -1}return 0}function C(E,G,H,F){var I=null;var J=0;if(E==160){I=B.floppy;if(B.floppy!=null){J=(B.floppy.size>>9)}}if(E==176){I=B.cdrom;if(B.cdrom!=null){J=(B.cdrom.size>>11)}}if((H<0)||(G+H>J)){B.SendCommandEndResponse(1,5,E,33,0);return 0}if(H==0){B.SendCommandEndResponse(1,0,E,0,0);return 0}if(I!=null){if(B.sectorStats){B.sectorStats(1,(E==160)?0:1,J,G,H)}if(E==160){G<<=9;H<<=9}else{G<<=11;H<<=11}if(d!==null){e.push({media:I,dev:E,lba:G,len:H,fr:F})}else{d=I;a=E;b=G;c=H;D(F)}}}var e=[];var f=false;var d=null;var a;var b;var c;function D(E){var G=c,F=b;if(c>B.iderinfo.readbfr){G=B.iderinfo.readbfr}c-=G;b+=G;var I=new Buffer(G);fs.readSync(d.file,I,0,G,F);B.SendDataToHost(a,(c==0),I,E&1);if((c>0)&&(f==false)){D(E)}else{d=null;if(f){B.SendCommand(71);e=[];f=false}else{if(e.length>0){var H=e.shift();d=H.media;a=H.dev;b=H.lba;c=H.len;D(H.fr)}}}}return B};function ShortToStr(a){return new Buffer([(a>>8)&255,a&255])}function ShortToStrX(a){return new Buffer([a&255,(a>>8)&255])}function IntToStr(a){return new Buffer([(a>>24)&255,(a>>16)&255,(a>>8)&255,a&255])}function IntToStrX(a){return new Buffer([a&255,(a>>8)&255,(a>>16)&255,(a>>24)&255])}function ReadShort(b,a){return(b[a]<<8)+b[a+1]}function ReadShortX(b,a){return(b[a+1]<<8)+b[a]}function ReadInt(b,a){return(b[a]*16777216)+(b[a+1]<<16)+(b[a+2]<<8)+b[a+3]}function ReadSInt(b,a){return(b[a]<<24)+(b[a+1]<<16)+(b[a+2]<<8)+b[a+3]}function ReadIntX(b,a){return(b[a+3]*16777216)+(b[a+2]<<16)+(b[a+1]<<8)+b[a]}; \ No newline at end of file diff --git a/agents/modules_meshcmd_min/amt-redir-duk.min.js b/agents/modules_meshcmd_min/amt-redir-duk.min.js new file mode 100644 index 00000000..3c9b759d --- /dev/null +++ b/agents/modules_meshcmd_min/amt-redir-duk.min.js @@ -0,0 +1 @@ +module.exports=function CreateAmtRedirect(a){var b={};b.m=a;a.parent=b;b.State=0;b.net=require("net");b.tls=require("tls");b.socket=null;b.host=null;b.port=0;b.user=null;b.pass=null;b.connectstate=0;b.protocol=a.protocol;b.xtlsoptions=null;b.amtaccumulator=null;b.amtsequence=1;b.amtkeepalivetimer=null;b.authuri="/RedirectionService";b.digestRealmMatch=null;b.onStateChanged=null;b.Debug=function(d){console.log(d)};var c=null;b.Start=function(d,f,k,e,g,h,j){b.host=d;b.port=f;b.user=k;b.pass=e;b.xtls=g;b.xtlsoptions=j;b.xtlsFingerprint=h;b.connectstate=0;if(g==true){b.socket=b.tls.connect({host:d,port:f,rejectUnauthorized:false,checkServerIdentity:b.onCheckServerIdentity},b.xxOnSocketConnected)}else{b.socket=b.net.createConnection({host:d,port:f},b.xxOnSocketConnected)}b.socket.on("data",b.xxOnSocketData);b.socket.on("close",b.xxOnSocketClosed);b.socket.on("error",b.xxOnSocketClosed);b.xxStateChange(1)};b.onCheckServerIdentity=function(d){var e=d[0].fingerprint.split(":").join("").toLowerCase();if((b.xtlsFingerprint!=null)&&(b.xtlsFingerprint!=e)){console.log("Invalid TLS Cert, SHA384: "+e);process.exit(2);return}else{if(b.xtlsFingerprint==null){b.xtlsFingerprint=e;console.log("TLS Cert SHA384: "+e)}}};b.xxOnSocketConnected=function(){if(b.socket==null){return}if(c&&c.redirtrace){console.log("REDIR-CONNECTED")}b.xxStateChange(2);if(b.protocol==1){b.xxSend(b.RedirectStartSol)}else{if(b.protocol==2){b.xxSend(b.RedirectStartKvm)}else{if(b.protocol==3){b.xxSend(b.RedirectStartIder)}}}};b.xxOnSocketData=function(n){if(!n||b.connectstate==-1){return}if(c&&c.redirtrace){console.log("REDIR-RECV("+n.length+"): "+n.toString("hex"))}if((b.protocol==2||b.protocol==3)&&b.connectstate==1){return b.m.ProcessData(n)}if(b.amtaccumulator==null){b.amtaccumulator=n}else{b.amtaccumulator=Buffer.concat(b.amtaccumulator,n)}while(b.amtaccumulator!=null){var j=0;switch(b.amtaccumulator[0]){case 17:if(b.amtaccumulator.length<4){return}var z=b.amtaccumulator[1];switch(z){case 0:if(b.amtaccumulator.length<13){return}var s=b.amtaccumulator[12];if(b.amtaccumulator.length<13+s){return}b.xxSend(String.fromCharCode(19,0,0,0,0,0,0,0,0));j=(13+s);break;default:b.Stop();break}break;case 20:if(b.amtaccumulator.length<9){return}var f=b.amtaccumulator.readInt32LE(5);if(b.amtaccumulator.length<9+f){return}var y=b.amtaccumulator[1];var g=b.amtaccumulator[4];var d=[];for(i=0;i=0){b.xxSend(String.fromCharCode(19,0,0,0,4)+IntToStrX(b.user.length+b.authuri.length+8)+String.fromCharCode(b.user.length)+b.user+String.fromCharCode(0,0)+String.fromCharCode(b.authuri.length)+b.authuri+String.fromCharCode(0,0,0,0))}else{if(d.indexOf(3)>=0){b.xxSend(String.fromCharCode(19,0,0,0,3)+IntToStrX(b.user.length+b.authuri.length+7)+String.fromCharCode(b.user.length)+b.user+String.fromCharCode(0,0)+String.fromCharCode(b.authuri.length)+b.authuri+String.fromCharCode(0,0,0))}else{if(d.indexOf(1)>=0){b.xxSend(String.fromCharCode(19,0,0,0,1)+IntToStrX(b.user.length+b.pass.length+2)+String.fromCharCode(b.user.length)+b.user+String.fromCharCode(b.pass.length)+b.pass)}else{b.Stop()}}}}else{if((g==3||g==4)&&y==1){var m=0;var w=e[m];var v=e.slice(m+1,m+1+w).toString();m+=(w+1);if(b.digestRealmMatch&&(b.digestRealmMatch!=v)){b.Stop();return}var r=e[m];var q=e.slice(m+1,m+1+r).toString();m+=(r+1);var u=0;var t=null;var k=b.xxRandomValueHex(32);var x="00000002";var p="";if(g==4){u=e[m];t=e.slice(m+1,m+1+u).toString();m+=(u+1);p=x+":"+k+":"+t+":"}var o=hex_md5(hex_md5(b.user+":"+v+":"+b.pass)+":"+q+":"+p+hex_md5("POST:"+b.authuri));var A=b.user.length+v.length+q.length+b.authuri.length+k.length+x.length+o.length+7;if(g==4){A+=(t.length+1)}var h=Buffer.concat([new Buffer([19,0,0,0,g]),new Buffer([A&255,(A>>8)&255,0,0]),new Buffer([b.user.length]),new Buffer(b.user),new Buffer([v.length]),new Buffer(v),new Buffer([q.length]),new Buffer(q),new Buffer([b.authuri.length]),new Buffer(b.authuri),new Buffer([k.length]),new Buffer(k),new Buffer([x.length]),new Buffer(x),new Buffer([o.length]),new Buffer(o)]);if(g==4){h=Buffer.concat([h,new Buffer([t.length]),new Buffer(t)])}b.xxSend(h)}else{if(y==0){if(b.protocol==1){}if(b.protocol==2){b.xxSend(new Buffer([64,0,0,0,0,0,0,0]))}if(b.protocol==3){b.connectstate=1;b.xxStateChange(3)}}else{b.Stop()}}}break;case 33:if(b.amtaccumulator.length<23){break}j=23;b.xxSend(String.fromCharCode(39,0,0,0)+ToIntStr(b.amtsequence++)+String.fromCharCode(0,0,27,0,0,0));if(b.protocol==1){b.amtkeepalivetimer=setInterval(b.xxSendAmtKeepAlive,2000)}b.connectstate=1;b.xxStateChange(3);break;case 41:if(b.amtaccumulator.length<10){break}j=10;break;case 42:if(b.amtaccumulator.length<10){break}var l=(10+((b.amtaccumulator[9]&255)<<8)+(b.amtaccumulator[8]&255));if(b.amtaccumulator.length8){b.m.ProcessData(b.amtaccumulator.substring(8))}j=b.amtaccumulator.length;break;default:console.log("Unknown Intel AMT command: "+b.amtaccumulator[0]+" acclen="+b.amtaccumulator.length);b.Stop();return}if(j==0){return}if(j==b.amtaccumulator.length){b.amtaccumulator=null}else{b.amtaccumulator=b.amtaccumulator.slice(j)}}};b.xxSend=function(d){if(c&&c.redirtrace){console.log("REDIR-SEND("+d.length+"): "+rstr2hex(d))}if(typeof d=="string"){b.socket.write(new Buffer(d,"binary"))}else{b.socket.write(d)}};b.Send=function(d){if(b.socket==null||b.connectstate!=1){return}if(b.protocol==1){b.xxSend(String.fromCharCode(40,0,0,0)+ToIntStr(b.amtsequence++)+ToShortStr(d.length)+d)}else{b.xxSend(d)}};b.xxSendAmtKeepAlive=function(){if(b.socket==null){return}b.xxSend(String.fromCharCode(43,0,0,0)+ToIntStr(b.amtsequence++))};b.xxRandomValueHex=function(f){var g=[],e=Math.floor(f/2);for(var d=0;d>8)&255),((a>>16)&255),((a>>24)&255))}function ToShortStr(a){return String.fromCharCode((a&255),((a>>8)&255))}function ShortToStr(a){return String.fromCharCode((a>>8)&255,a&255)}function ShortToStrX(a){return String.fromCharCode(a&255,(a>>8)&255)}function IntToStr(a){return String.fromCharCode((a>>24)&255,(a>>16)&255,(a>>8)&255,a&255)}function IntToStrX(a){return String.fromCharCode(a&255,(a>>8)&255,(a>>16)&255,(a>>24)&255)}var md5hasher=require("MD5Stream").create();function hex_md5(b){return md5hasher.syncHash(b).toString("hex").toLowerCase()}; \ No newline at end of file diff --git a/meshagent.js b/meshagent.js index 6bab1968..5613e977 100644 --- a/meshagent.js +++ b/meshagent.js @@ -696,7 +696,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { } } - completeAgentConnection3(); + completeAgentConnection3(device); }); } @@ -736,10 +736,10 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id }); } - completeAgentConnection3(); + completeAgentConnection3(device); } - function completeAgentConnection3() { + function completeAgentConnection3(device) { // Check if this agent is already connected const dupAgent = parent.wsagents[obj.dbNodeKey]; parent.wsagents[obj.dbNodeKey] = obj; diff --git a/package.json b/package.json index 2cd696aa..a277a8a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.3.6-a", + "version": "0.3.6-b", "keywords": [ "Remote Management", "Intel AMT",