diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 3fde67be..1122fa50 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 7e429030..88cc431b 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 e50c1c2a..0ba4016b 100644 --- a/agents/meshcmd.js +++ b/agents/meshcmd.js @@ -57,7 +57,6 @@ var Small_IntelAmtWebApp = "H4sIAAAAAAAEAHq/e7+Noou/c0hkgCuA0+pcchQHwq9CeXNgFzwZ function onVerifyServer(clientName, certs) { if (certs == null) { certs = clientName; } // Temporary thing until we fix duktape try { for (var i in certs) { if (certs[i].fingerprint.replace(/:/g, '') == settings.serverhttpshash) { return; } } } catch (e) { } - console.log(settings.serverhttpshash); if (settings.serverhttpshash != null) { console.log('Error: Failed to verify server certificate.'); console.log('Server TLS hash: ' + certs[i].fingerprint.replace(/:/g, '')); @@ -116,6 +115,7 @@ function run(argv) { if ((typeof args.action) == 'string') { settings.action = args.action; } if ((typeof args.localport) == 'string') { settings.localport = parseInt(args.localport); } if ((typeof args.remotenodeid) == 'string') { settings.remotenodeid = args.remotenodeid; } + if ((typeof args.name) == 'string') { settings.name = args.name; } if ((typeof args.username) == 'string') { settings.username = args.username; } if ((typeof args.password) == 'string') { settings.password = args.password; } if ((typeof args.url) == 'string') { settings.url = args.url; } @@ -137,6 +137,7 @@ function run(argv) { 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.tag) == 'string') { settings.tag = args.tag; } if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); } if (args.debug === true) { settings.debuglevel = 1; } if (args.debug) { try { waitForDebugger(); } catch (e) { } } @@ -209,12 +210,21 @@ function run(argv) { console.log('\r\nRun as a background service:\r\n'); console.log(' microlms install/uninstall/start/stop.'); } else if (action == 'amtccm') { - console.log('AmtCCM will attempt to activate Intel AMT on this computer into client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work and a administrator password must be provided. Example usage:\r\n\r\n meshcmd amtccm --pass mypassword'); + console.log('AmtCCM will attempt to activate Intel AMT on this computer into client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work and a administrator password must be provided.'); + console.log('\r\nPossible arguments:\r\n'); + console.log(' --password [password] Admin password used to activate Intel AMT.'); + console.log('\r\nor:\r\n'); + console.log(' --url [wss://server] Url to the activation server.'); + console.log(' --tag [string] Optional string sent to the server during activation.'); + console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.'); + console.log(' --profile [string] Optional profile used for server activation.'); } else if (action == 'amtacm') { console.log('AmtACM will attempt to activate Intel AMT on this computer into admin control mode (ACM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work. Example usage:\r\n\r\n meshcmd amtacm --url [url]'); console.log('\r\nPossible arguments:\r\n'); - console.log(' --url wss://server/ The address of the Intel AMT activation server.'); - console.log(' --profile [name] Optional name of the Intel AMT profile stored on the activation server.'); + console.log(' --url [wss://server] The address of the Intel AMT activation server.'); + console.log(' --tag [string] Optional string sent to the server during activation.'); + console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.'); + console.log(' --profile [string] Optional profile used for server activation.'); } else if (action == 'amtdeactivate') { console.log('AmtDeactivate will attempt to deactivate Intel AMT on this computer when in client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be activated in client control mode for this command to work. Example usage:\r\n\r\n meshcmd amtdeactivate'); } else if (action == 'amtacmdeactivate') { @@ -497,11 +507,12 @@ function run(argv) { getAmtUuid(); } else if (settings.action == 'amtccm') { // Start activation to CCM - 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.password == null) || (typeof settings.password != 'string') || (settings.password == '')) && ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == ''))) { console.log('No or invalid parameters specified, use --password [password] or --url [url].'); exit(1); return; } + if ((typeof settings.profile != 'string') || (settings.profile == '')) { settings.profile = null; } settings.protocol = 'http:'; settings.localport = 16992; debug(1, "Settings: " + JSON.stringify(settings)); - activeToCCM(); + if (settings.password != null) { activeToCCM(); } else { activeServerCCM(); } } else if (settings.action == 'amtacm') { // Start activation to ACM if ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == '')) { console.log('No activation server URL specified, use --url [url].'); exit(1); return; } @@ -806,6 +817,94 @@ function activeToCCMEx3(stack, name, responses, status) { exit(1); } + +// +// Activate Intel AMT to CCM with server activation +// + +function activeServerCCM() { + settings.noconsole = true; + mestate = {}; + var amtMeiModule, amtMei; + try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { console.log(ex); exit(1); return; } + amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); + amtMei.getProvisioningState(function (result) { if (result) { mestate.ProvisioningState = result; } }); + amtMei.getVersion(function (val) { mestate.vers = {}; if (val != null) { for (var version in val.Versions) { mestate.vers[val.Versions[version].Description] = val.Versions[version].Version; } } }); + amtMei.getUuid(function (result) { + if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } + if ((mestate.vers == null) || (mestate.vers['AMT'] == null)) { console.log("Unable to get Intel AMT version."); exit(100); return; } + if (mestate.ProvisioningState == null) { console.log("Unable to read Intel AMT activation state."); exit(100); return; } + if (mestate.ProvisioningState.state !== 0) { console.log("Intel AMT is not in pre-provisioning state: " + mestate.ProvisioningState.stateStr); exit(100); return; } + if (mestate.uuid == null) { console.log("Unable to get Intel AMT UUID."); exit(100); return; } + startLms(activeServerCCMEx); + }); +} + +function activeServerCCMEx(state) { + osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeServerCCMEx2); +} + +function activeServerCCMEx2(stack, name, responses, status) { + if (status != 200) { console.log('Failed to fetch activation status, status ' + status); exit(1); } + else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { console.log('Client control mode activation not allowed'); exit(1); } + + // Establish WebSocket connection to activation server + var options = http.parseUri(settings.url); + options.checkServerIdentity = onVerifyServer; + options.rejectUnauthorized = false; + var connection = http.request(options); + connection.on('upgrade', function (response, socket) { + console.log('Connected, requesting activation...'); + settings.xxsocket = socket; + socket.on('end', function () { console.log('Connection closed'); exit(0); }); + socket.on('error', function () { console.log('Connection error'); exit(100); }); + socket.on('data', function (data) { + // Parse and check the response + var cmd = null; + try { cmd = JSON.parse(data); } catch (ex) { console.log('Unable to parse server response: ' + data); exit(100); return; } + if (typeof cmd != 'object') { console.log('Invalid server response: ' + cmd); exit(100); return; } + if (typeof cmd.errorText == 'string') { console.log('Server error: ' + cmd.errorText); exit(100); return; } + if (cmd.action != 'ccmactivate') { console.log('Invalid server response, command: ' + cmd.cmd); exit(100); return; } + if (typeof cmd.password != 'string') { console.log('Invalid server password'); exit(100); return; } + settings.xxprofileScript = cmd.profileScript; + settings.xxrawpassword = cmd.rawpassword; + + // We are ready to go, perform CCM activation. + osamtstack.IPS_HostBasedSetupService_Setup(2, cmd.password, null, null, null, null, activeServerCCMEx3); + }); + socket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate', realm: responses['AMT_GeneralSettings'].response['DigestRealm'], uuid: mestate.uuid, tag: settings.tag, name: settings.name, ver: mestate.vers['AMT'] }); + }); + connection.end(); +} + +function activeServerCCMEx3(stack, name, responses, status) { + if (status != 200) { + settings.xxsocket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate-failed', uuid: mestate.uuid }); + console.log('Failed to activate, status ' + status); + } else if (responses.Body.ReturnValue != 0) { + settings.xxsocket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate-failed', uuid: mestate.uuid }); + console.log('Client control mode activation failed: ' + responses.Body.ReturnValueStr); + } else { + settings.xxsocket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate-success', uuid: mestate.uuid }); + if ((settings.xxprofileScript !== null) && (settings.xxrawpassword != null)) { + console.log("Intel AMT ACM activation success, applying profile..."); + settings.scriptjson = settings.xxprofileScript; + settings.password = settings.xxrawpassword; // This is only going to work if the server sends the raw password + settings.username = 'admin'; + startMeScriptEx(function () { console.log('Intel AMT profile applied.'); socket.end(); exit(0); }, stack); + return; + } else { + console.log('Success'); + settings.xxsocket.end(); + exit(0); + return; + } + } + settings.xxsocket.end(); + exit(1); +} + + // // Deactivate Intel AMT ACM // @@ -858,7 +957,6 @@ function deactivateACMEx() { var trustedHashes = null; function getTrustedHashes(amtMei, func, tag) { - console.log('getTrustedHashes'); if (trustedHashes != null) { func(tag); } trustedHashes = []; amtMei.getHashHandles(function (handles) { @@ -886,9 +984,12 @@ function activeToACM() { try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { console.log(ex); exit(1); return; } amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); amtMei.getProvisioningState(function (result) { if (result) { mestate.ProvisioningState = result; } }); + amtMei.getVersion(function (val) { mestate.vers = {}; if (val != null) { for (var version in val.Versions) { mestate.vers[val.Versions[version].Description] = val.Versions[version].Version; } } }); amtMei.getLanInterfaceSettings(0, function (result) { if (result) { mestate.net0 = result; } }); amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } }); amtMei.getDnsSuffix(function (result) { + if ((mestate.vers == null) || (mestate.vers['AMT'] == null)) { console.log("Unable to get Intel AMT version."); exit(100); return; } + if (mestate.ProvisioningState == null) { console.log("Unable to read Intel AMT activation state."); exit(100); return; } if (mestate.ProvisioningState.state !== 0) { console.log("Intel AMT is not in pre-provisioning state: " + mestate.ProvisioningState.stateStr); exit(100); return; } if (mestate.uuid == null) { console.log("Unable to get Intel AMT UUID."); exit(100); return; } var fqdn = null; @@ -958,22 +1059,26 @@ function activeToACMEx(fwNonce, dnsSuffix, digestRealm, uuid) { performAcmActivation(cmd, function (result) { if (result == false) { console.log('Intel AMT ACM activation failed.'); + socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate-failed', uuid: mestate.uuid }); + socket.end(); + exit(1); } else { if ((cmd.profileScript !== null) && (cmd.rawpassword != null)) { - console.log("Intel AMT ACM activation success, applying profile..."); + console.log('Intel AMT ACM activation success, applying profile...'); settings.scriptjson = cmd.profileScript; - settings.password = cmd.rawpassword; // TODO: This is only going to work if the server sends the raw password?? + settings.password = cmd.rawpassword; // This is only going to work if the server sends the raw password settings.username = 'admin'; startMeScriptEx(function () { console.log('Intel AMT profile applied.'); socket.end(); exit(0); }, stack); } else { console.log('Intel AMT ACM activation success.'); + socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate-success', uuid: mestate.uuid }); socket.end(); exit(0); } } }); }); - socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate', fqdn: dnsSuffix, realm: digestRealm, nonce: fwNonce, uuid: uuid, profile: settings.profile, hashes: trustedHashes }); + socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate', fqdn: dnsSuffix, realm: digestRealm, nonce: fwNonce, uuid: uuid, profile: settings.profile, hashes: trustedHashes, tag: settings.tag, name: settings.name, ver: mestate.vers['AMT'] }); }); connection.end(); } @@ -983,13 +1088,18 @@ function performAcmActivation(acmdata, func) { var leaf = (acmdata.index == 0), root = (acmdata.index == (acmdata.certs.length - 1)); if ((acmdata.index < acmdata.certs.length) && (acmdata.certs[acmdata.index] != null)) { osamtstack.IPS_HostBasedSetupService_AddNextCertInChain(acmdata.certs[acmdata.index], leaf, root, function (stack, name, responses, status) { - if (status !== 200) { debug('AddNextCertInChain status=' + status); return; } - else if (responses['Body']['ReturnValue'] !== 0) { debug('AddNextCertInChain error=' + responses['Body']['ReturnValue']); return; } + if (status !== 200) { debug('AddNextCertInChain status: ' + status); return; } + else if (responses['Body']['ReturnValue'] !== 0) { console.log('AddNextCertInChain error: ' + responses['Body']['ReturnValue']); return; } else { acmdata.index++; performAcmActivation(acmdata, func); } }); } else { + console.log(acmdata.password, acmdata.nonce, acmdata.signature); osamtstack.IPS_HostBasedSetupService_AdminSetup(2, acmdata.password, acmdata.nonce, 2, acmdata.signature, - function (stack, name, responses, status) { func((status == 200) && (responses['Body']['ReturnValue'] == 0)); } + function (stack, name, responses, status) { + if (status !== 200) { console.log('Error, AdminSetup status: ' + status); } + else if (responses['Body']['ReturnValue'] != 0) { console.log('Error, AdminSetup return value: ' + responses['Body']['ReturnValue']); } + func((status == 200) && (responses['Body']['ReturnValue'] == 0)); + } ); } } diff --git a/agents/meshcmd.min.js b/agents/meshcmd.min.js index e50c1c2a..0ba4016b 100644 --- a/agents/meshcmd.min.js +++ b/agents/meshcmd.min.js @@ -57,7 +57,6 @@ var Small_IntelAmtWebApp = "H4sIAAAAAAAEAHq/e7+Noou/c0hkgCuA0+pcchQHwq9CeXNgFzwZ function onVerifyServer(clientName, certs) { if (certs == null) { certs = clientName; } // Temporary thing until we fix duktape try { for (var i in certs) { if (certs[i].fingerprint.replace(/:/g, '') == settings.serverhttpshash) { return; } } } catch (e) { } - console.log(settings.serverhttpshash); if (settings.serverhttpshash != null) { console.log('Error: Failed to verify server certificate.'); console.log('Server TLS hash: ' + certs[i].fingerprint.replace(/:/g, '')); @@ -116,6 +115,7 @@ function run(argv) { if ((typeof args.action) == 'string') { settings.action = args.action; } if ((typeof args.localport) == 'string') { settings.localport = parseInt(args.localport); } if ((typeof args.remotenodeid) == 'string') { settings.remotenodeid = args.remotenodeid; } + if ((typeof args.name) == 'string') { settings.name = args.name; } if ((typeof args.username) == 'string') { settings.username = args.username; } if ((typeof args.password) == 'string') { settings.password = args.password; } if ((typeof args.url) == 'string') { settings.url = args.url; } @@ -137,6 +137,7 @@ function run(argv) { 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.tag) == 'string') { settings.tag = args.tag; } if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); } if (args.debug === true) { settings.debuglevel = 1; } if (args.debug) { try { waitForDebugger(); } catch (e) { } } @@ -209,12 +210,21 @@ function run(argv) { console.log('\r\nRun as a background service:\r\n'); console.log(' microlms install/uninstall/start/stop.'); } else if (action == 'amtccm') { - console.log('AmtCCM will attempt to activate Intel AMT on this computer into client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work and a administrator password must be provided. Example usage:\r\n\r\n meshcmd amtccm --pass mypassword'); + console.log('AmtCCM will attempt to activate Intel AMT on this computer into client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work and a administrator password must be provided.'); + console.log('\r\nPossible arguments:\r\n'); + console.log(' --password [password] Admin password used to activate Intel AMT.'); + console.log('\r\nor:\r\n'); + console.log(' --url [wss://server] Url to the activation server.'); + console.log(' --tag [string] Optional string sent to the server during activation.'); + console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.'); + console.log(' --profile [string] Optional profile used for server activation.'); } else if (action == 'amtacm') { console.log('AmtACM will attempt to activate Intel AMT on this computer into admin control mode (ACM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be in "pre-provisioning" state for this command to work. Example usage:\r\n\r\n meshcmd amtacm --url [url]'); console.log('\r\nPossible arguments:\r\n'); - console.log(' --url wss://server/ The address of the Intel AMT activation server.'); - console.log(' --profile [name] Optional name of the Intel AMT profile stored on the activation server.'); + console.log(' --url [wss://server] The address of the Intel AMT activation server.'); + console.log(' --tag [string] Optional string sent to the server during activation.'); + console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.'); + console.log(' --profile [string] Optional profile used for server activation.'); } else if (action == 'amtdeactivate') { console.log('AmtDeactivate will attempt to deactivate Intel AMT on this computer when in client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be activated in client control mode for this command to work. Example usage:\r\n\r\n meshcmd amtdeactivate'); } else if (action == 'amtacmdeactivate') { @@ -497,11 +507,12 @@ function run(argv) { getAmtUuid(); } else if (settings.action == 'amtccm') { // Start activation to CCM - 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.password == null) || (typeof settings.password != 'string') || (settings.password == '')) && ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == ''))) { console.log('No or invalid parameters specified, use --password [password] or --url [url].'); exit(1); return; } + if ((typeof settings.profile != 'string') || (settings.profile == '')) { settings.profile = null; } settings.protocol = 'http:'; settings.localport = 16992; debug(1, "Settings: " + JSON.stringify(settings)); - activeToCCM(); + if (settings.password != null) { activeToCCM(); } else { activeServerCCM(); } } else if (settings.action == 'amtacm') { // Start activation to ACM if ((settings.url == null) || (typeof settings.url != 'string') || (settings.url == '')) { console.log('No activation server URL specified, use --url [url].'); exit(1); return; } @@ -806,6 +817,94 @@ function activeToCCMEx3(stack, name, responses, status) { exit(1); } + +// +// Activate Intel AMT to CCM with server activation +// + +function activeServerCCM() { + settings.noconsole = true; + mestate = {}; + var amtMeiModule, amtMei; + try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { console.log(ex); exit(1); return; } + amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); + amtMei.getProvisioningState(function (result) { if (result) { mestate.ProvisioningState = result; } }); + amtMei.getVersion(function (val) { mestate.vers = {}; if (val != null) { for (var version in val.Versions) { mestate.vers[val.Versions[version].Description] = val.Versions[version].Version; } } }); + amtMei.getUuid(function (result) { + if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } + if ((mestate.vers == null) || (mestate.vers['AMT'] == null)) { console.log("Unable to get Intel AMT version."); exit(100); return; } + if (mestate.ProvisioningState == null) { console.log("Unable to read Intel AMT activation state."); exit(100); return; } + if (mestate.ProvisioningState.state !== 0) { console.log("Intel AMT is not in pre-provisioning state: " + mestate.ProvisioningState.stateStr); exit(100); return; } + if (mestate.uuid == null) { console.log("Unable to get Intel AMT UUID."); exit(100); return; } + startLms(activeServerCCMEx); + }); +} + +function activeServerCCMEx(state) { + osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeServerCCMEx2); +} + +function activeServerCCMEx2(stack, name, responses, status) { + if (status != 200) { console.log('Failed to fetch activation status, status ' + status); exit(1); } + else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { console.log('Client control mode activation not allowed'); exit(1); } + + // Establish WebSocket connection to activation server + var options = http.parseUri(settings.url); + options.checkServerIdentity = onVerifyServer; + options.rejectUnauthorized = false; + var connection = http.request(options); + connection.on('upgrade', function (response, socket) { + console.log('Connected, requesting activation...'); + settings.xxsocket = socket; + socket.on('end', function () { console.log('Connection closed'); exit(0); }); + socket.on('error', function () { console.log('Connection error'); exit(100); }); + socket.on('data', function (data) { + // Parse and check the response + var cmd = null; + try { cmd = JSON.parse(data); } catch (ex) { console.log('Unable to parse server response: ' + data); exit(100); return; } + if (typeof cmd != 'object') { console.log('Invalid server response: ' + cmd); exit(100); return; } + if (typeof cmd.errorText == 'string') { console.log('Server error: ' + cmd.errorText); exit(100); return; } + if (cmd.action != 'ccmactivate') { console.log('Invalid server response, command: ' + cmd.cmd); exit(100); return; } + if (typeof cmd.password != 'string') { console.log('Invalid server password'); exit(100); return; } + settings.xxprofileScript = cmd.profileScript; + settings.xxrawpassword = cmd.rawpassword; + + // We are ready to go, perform CCM activation. + osamtstack.IPS_HostBasedSetupService_Setup(2, cmd.password, null, null, null, null, activeServerCCMEx3); + }); + socket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate', realm: responses['AMT_GeneralSettings'].response['DigestRealm'], uuid: mestate.uuid, tag: settings.tag, name: settings.name, ver: mestate.vers['AMT'] }); + }); + connection.end(); +} + +function activeServerCCMEx3(stack, name, responses, status) { + if (status != 200) { + settings.xxsocket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate-failed', uuid: mestate.uuid }); + console.log('Failed to activate, status ' + status); + } else if (responses.Body.ReturnValue != 0) { + settings.xxsocket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate-failed', uuid: mestate.uuid }); + console.log('Client control mode activation failed: ' + responses.Body.ReturnValueStr); + } else { + settings.xxsocket.write({ client: 'meshcmd', version: 1, action: 'ccmactivate-success', uuid: mestate.uuid }); + if ((settings.xxprofileScript !== null) && (settings.xxrawpassword != null)) { + console.log("Intel AMT ACM activation success, applying profile..."); + settings.scriptjson = settings.xxprofileScript; + settings.password = settings.xxrawpassword; // This is only going to work if the server sends the raw password + settings.username = 'admin'; + startMeScriptEx(function () { console.log('Intel AMT profile applied.'); socket.end(); exit(0); }, stack); + return; + } else { + console.log('Success'); + settings.xxsocket.end(); + exit(0); + return; + } + } + settings.xxsocket.end(); + exit(1); +} + + // // Deactivate Intel AMT ACM // @@ -858,7 +957,6 @@ function deactivateACMEx() { var trustedHashes = null; function getTrustedHashes(amtMei, func, tag) { - console.log('getTrustedHashes'); if (trustedHashes != null) { func(tag); } trustedHashes = []; amtMei.getHashHandles(function (handles) { @@ -886,9 +984,12 @@ function activeToACM() { try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { console.log(ex); exit(1); return; } amtMei.on('error', function (e) { console.log('ERROR: ' + e); exit(1); return; }); amtMei.getProvisioningState(function (result) { if (result) { mestate.ProvisioningState = result; } }); + amtMei.getVersion(function (val) { mestate.vers = {}; if (val != null) { for (var version in val.Versions) { mestate.vers[val.Versions[version].Description] = val.Versions[version].Version; } } }); amtMei.getLanInterfaceSettings(0, function (result) { if (result) { mestate.net0 = result; } }); amtMei.getUuid(function (result) { if ((result != null) && (result.uuid != null)) { mestate.uuid = result.uuid; } }); amtMei.getDnsSuffix(function (result) { + if ((mestate.vers == null) || (mestate.vers['AMT'] == null)) { console.log("Unable to get Intel AMT version."); exit(100); return; } + if (mestate.ProvisioningState == null) { console.log("Unable to read Intel AMT activation state."); exit(100); return; } if (mestate.ProvisioningState.state !== 0) { console.log("Intel AMT is not in pre-provisioning state: " + mestate.ProvisioningState.stateStr); exit(100); return; } if (mestate.uuid == null) { console.log("Unable to get Intel AMT UUID."); exit(100); return; } var fqdn = null; @@ -958,22 +1059,26 @@ function activeToACMEx(fwNonce, dnsSuffix, digestRealm, uuid) { performAcmActivation(cmd, function (result) { if (result == false) { console.log('Intel AMT ACM activation failed.'); + socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate-failed', uuid: mestate.uuid }); + socket.end(); + exit(1); } else { if ((cmd.profileScript !== null) && (cmd.rawpassword != null)) { - console.log("Intel AMT ACM activation success, applying profile..."); + console.log('Intel AMT ACM activation success, applying profile...'); settings.scriptjson = cmd.profileScript; - settings.password = cmd.rawpassword; // TODO: This is only going to work if the server sends the raw password?? + settings.password = cmd.rawpassword; // This is only going to work if the server sends the raw password settings.username = 'admin'; startMeScriptEx(function () { console.log('Intel AMT profile applied.'); socket.end(); exit(0); }, stack); } else { console.log('Intel AMT ACM activation success.'); + socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate-success', uuid: mestate.uuid }); socket.end(); exit(0); } } }); }); - socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate', fqdn: dnsSuffix, realm: digestRealm, nonce: fwNonce, uuid: uuid, profile: settings.profile, hashes: trustedHashes }); + socket.write({ client: 'meshcmd', version: 1, action: 'acmactivate', fqdn: dnsSuffix, realm: digestRealm, nonce: fwNonce, uuid: uuid, profile: settings.profile, hashes: trustedHashes, tag: settings.tag, name: settings.name, ver: mestate.vers['AMT'] }); }); connection.end(); } @@ -983,13 +1088,18 @@ function performAcmActivation(acmdata, func) { var leaf = (acmdata.index == 0), root = (acmdata.index == (acmdata.certs.length - 1)); if ((acmdata.index < acmdata.certs.length) && (acmdata.certs[acmdata.index] != null)) { osamtstack.IPS_HostBasedSetupService_AddNextCertInChain(acmdata.certs[acmdata.index], leaf, root, function (stack, name, responses, status) { - if (status !== 200) { debug('AddNextCertInChain status=' + status); return; } - else if (responses['Body']['ReturnValue'] !== 0) { debug('AddNextCertInChain error=' + responses['Body']['ReturnValue']); return; } + if (status !== 200) { debug('AddNextCertInChain status: ' + status); return; } + else if (responses['Body']['ReturnValue'] !== 0) { console.log('AddNextCertInChain error: ' + responses['Body']['ReturnValue']); return; } else { acmdata.index++; performAcmActivation(acmdata, func); } }); } else { + console.log(acmdata.password, acmdata.nonce, acmdata.signature); osamtstack.IPS_HostBasedSetupService_AdminSetup(2, acmdata.password, acmdata.nonce, 2, acmdata.signature, - function (stack, name, responses, status) { func((status == 200) && (responses['Body']['ReturnValue'] == 0)); } + function (stack, name, responses, status) { + if (status !== 200) { console.log('Error, AdminSetup status: ' + status); } + else if (responses['Body']['ReturnValue'] != 0) { console.log('Error, AdminSetup return value: ' + responses['Body']['ReturnValue']); } + func((status == 200) && (responses['Body']['ReturnValue'] == 0)); + } ); } } diff --git a/certoperations.js b/certoperations.js index 123f21e6..dcc1663d 100644 --- a/certoperations.js +++ b/certoperations.js @@ -62,7 +62,7 @@ module.exports.CertificateOperations = function (parent) { } catch (ex) { return { 'action': 'acmactivate', 'error': 4, 'errorText': 'Unable to perform signature' }; } // Log the activation request, logging is a required step for activation. - if (obj.logAmtActivation(domain, { time: new Date(), domain: domain.id, amtUuid: request.uuid, certHash: request.hash, hashType: hashAlgo, amtRealm: request.realm, amtFqdn: request.fqdn, user: user, password: pass, ipport: ipport, nodeid: nodeid, meshid: meshid, computerName: computerName, agentId: agentId }) == false) return { 'action': 'acmactivate', 'error': 5, 'errorText': 'Unable to log operation' }; + if (obj.logAmtActivation(domain, { time: new Date(), action: 'acmactivate', domain: domain.id, amtUuid: request.uuid, certHash: request.hash, hashType: hashAlgo, amtRealm: request.realm, amtFqdn: request.fqdn, user: user, password: pass, ipport: ipport, nodeid: nodeid, meshid: meshid, computerName: computerName, agentId: agentId, tag: request.tag, name: request.name }) == false) return { 'action': 'acmactivate', 'error': 5, 'errorText': 'Unable to log operation' }; // Return the signature with the computed account password hash return { 'action': 'acmactivate', 'signature': signature, 'password': obj.crypto.createHash('md5').update(user + ':' + request.realm + ':' + pass).digest('hex'), 'nonce': mcNonce.toString('base64'), 'certs': certChain }; diff --git a/db.js b/db.js index 48967048..c0168354 100644 --- a/db.js +++ b/db.js @@ -864,6 +864,7 @@ module.exports.CreateDB = function (parent, func) { mesh.nolog = 1; delete mesh.type; delete mesh._id; + if (mesh.amt) { delete mesh.amt.password; } // Remove the Intel AMT password if present parent.DispatchEvent(['*', mesh._id], obj, mesh); } diff --git a/meshagent.js b/meshagent.js index 5161295c..9faa97c6 100644 --- a/meshagent.js +++ b/meshagent.js @@ -1232,7 +1232,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { ChangeAgentCoreInfo({ "intelamt": { user: 'admin', pass: amtpassword, uuid: command.uuid, realm: command.realm } }); // Send the activation response - //obj.send(JSON.stringify(signResponse)); // DEBUG**************************** + obj.send(JSON.stringify(signResponse)); } break; } diff --git a/meshuser.js b/meshuser.js index 1636fdce..765032dd 100644 --- a/meshuser.js +++ b/meshuser.js @@ -363,7 +363,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use { // Request a list of all meshes this user as rights to var docs = []; - for (i in user.links) { if ((parent.meshes[i]) && (parent.meshes[i].deleted == null)) { docs.push(parent.meshes[i]); } } + for (i in user.links) { + if ((parent.meshes[i]) && (parent.meshes[i].deleted == null)) { + if (parent.meshes[i].amt && parent.meshes[i].amt.password) { + // Remove the Intel AMT password if present + var m = common.Clone(parent.meshes[i]); delete m.amt.password; docs.push(m); + } else { + docs.push(parent.meshes[i]); + } + } + } try { ws.send(JSON.stringify({ action: 'meshes', meshes: docs, tag: command.tag })); } catch (ex) { } break; } @@ -1589,7 +1598,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (common.validateInt(command.amtpolicy.type, 0, 3) == false) break; // Check the amtpolicy.type if (command.amtpolicy.type === 2) { if (common.validateString(command.amtpolicy.password, 0, 32) == false) break; // Check the amtpolicy.password - if (common.validateInt(command.amtpolicy.badpass, 0, 1) == false) break; // Check the amtpolicy.badpass + if ((command.amtpolicy.badpass != null) && common.validateInt(command.amtpolicy.badpass, 0, 1) == false) break; // Check the amtpolicy.badpass if (common.validateInt(command.amtpolicy.cirasetup, 0, 2) == false) break; // Check the amtpolicy.cirasetup } else if (command.amtpolicy.type === 3) { if (common.validateString(command.amtpolicy.password, 0, 32) == false) break; // Check the amtpolicy.password @@ -1611,7 +1620,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use else if (command.amtpolicy.type === 3) { amtpolicy = { type: command.amtpolicy.type, password: command.amtpolicy.password, cirasetup: command.amtpolicy.cirasetup }; } mesh.amt = amtpolicy; db.Set(common.escapeLinksFieldName(mesh)); - var event = { etype: 'mesh', username: user.name, meshid: mesh._id, amt: amtpolicy, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }; + var amtpolicy2 = common.Clone(amtpolicy); + delete amtpolicy2.password; + var event = { etype: 'mesh', username: user.name, meshid: mesh._id, amt: amtpolicy2, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, event); @@ -1653,7 +1664,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use parent.crypto.randomBytes(48, function (err, buf) { // create the new node nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); - var device = { type: 'node', mtype: 1, _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } }; + var device = { type: 'node', _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } }; db.Set(device); // Event the new node diff --git a/views/default-min.handlebars b/views/default-min.handlebars index 86a62344..466ade27 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -7903,15 +7903,19 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this } if (message.event.node.intelamt != null) { if (node.intelamt == null) node.intelamt = {}; + if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; } if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; } if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; } if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; } if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; } - if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; } + if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; } + if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; } + if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; } } node.namel = node.name.toLowerCase(); if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; } if (message.event.node.icon) { node.icon = message.event.node.icon; } + console.log(node); // Web page update masterUpdate(2 | 4 | 8 | 16); @@ -8632,6 +8636,11 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this r += ' Add Local'; r += ' Scan Network'; } + if (mesh.amt && (mesh.amt.type == 2)) { // CCM activation + r += ' Activation'; + } else if (mesh.amt && (mesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation + r += ' Activation'; + } } if (mesh.mtype == 2) { r += ' Add Agent'; @@ -8654,6 +8663,45 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this Q('dp1devicename').focus(); } + // Intel AMT CCM Activation + function showCcmActivation(meshid) { + if (xxdialogMode) return; + var servername = serverinfo.name, mesh = meshes[meshid]; + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name. + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1); + if (serverinfo.https == true) { + var portStr = (serverinfo.port == 443) ? '' : (":" + serverinfo.port); + url = "wss://" + servername + portStr + domainUrl; + } else { + var portStr = (serverinfo.port == 80) ? '' : (":" + serverinfo.port); + url = "ws://" + servername + portStr + domainUrl; + } + var x = "Perform Intel AMT client control mode (CCM) activation to group \"" + EscapeHtml(mesh.name) + "\" by downloading the MeshCMD tool and running it like this:

"; + x += ''; + setDialogMode(2, "Intel® AMT activation", 9, null, x); + } + + // Intel AMT ACM Activation + function showAcmActivation(meshid) { + if (xxdialogMode) return; + var servername = serverinfo.name, mesh = meshes[meshid]; + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name. + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1); + if (serverinfo.https == true) { + var portStr = (serverinfo.port == 443) ? '' : (":" + serverinfo.port); + url = "wss://" + servername + portStr + domainUrl; + } else { + var portStr = (serverinfo.port == 80) ? '' : (":" + serverinfo.port); + url = "ws://" + servername + portStr + domainUrl; + } + var x = "Perform Intel AMT admin control mode (ACM) activation to group \"" + EscapeHtml(mesh.name) + "\" by downloading the MeshCMD tool and running it like this:

"; + x += ''; + if (serverinfo.amtAcmFqdn != null) { + x += '
Intel AMT will need to be set with a Trusted FQDN in MEBx or have a wired LAN on the network: ' + serverinfo.amtAcmFqdn.join(', ') + '
'; + } + setDialogMode(2, "Intel® AMT activation", 9, null, x); + } + // Display the Intel AMT scanning dialog box function addAmtScanToMesh(meshid) { if (xxdialogMode) return; @@ -9887,11 +9935,20 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this x += addDeviceAttribute('Intel® AMT', str); } - // Attribute: Mesh Agent Tag - if ((node.agent != null) && (node.agent.tag != null) && (node.agent.tag != 'mailto:')) { - var tag = EscapeHtml(node.agent.tag); - if (tag.startsWith('mailto:')) { tag = '' + tag.substring(7) + ''; } - x += addDeviceAttribute('Agent Tag', tag); + if (mesh.mtype == 2) { + // Attribute: Mesh Agent Tag + if ((node.agent != null) && (node.agent.tag != null)) { + var tag = EscapeHtml(node.agent.tag); + if (tag.startsWith('mailto:')) { tag = '' + tag.substring(7) + ''; } + x += addDeviceAttribute('Agent Tag', tag); + } + } else { + // Attribute: Intel AMT Tag + if ((node.intelamt != null) && (node.intelamt.tag != null)) { + var tag = EscapeHtml(node.intelamt.tag); + if (tag.startsWith('mailto:')) { tag = '' + tag.substring(7) + ''; } + x += addDeviceAttribute('Intel® AMT Tag', tag); + } } // Attribute: Intel AMT @@ -12244,14 +12301,16 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]); // Display features - var meshFeatures = []; - if (currentMesh.flags) { - if (currentMesh.flags & 1) { meshFeatures.push('Auto-Remove'); } - if (currentMesh.flags & 2) { meshFeatures.push('Hostname Sync'); } + if (currentMesh.mtype == 2) { + var meshFeatures = []; + if (currentMesh.flags) { + if (currentMesh.flags & 1) { meshFeatures.push('Auto-Remove'); } + if (currentMesh.flags & 2) { meshFeatures.push('Hostname Sync'); } + } + meshFeatures = meshFeatures.join(', '); + if (meshFeatures == '') { meshFeatures = 'None'; } + x += addHtmlValue('Features', addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1)); } - meshFeatures = meshFeatures.join(', '); - if (meshFeatures == '') { meshFeatures = 'None'; } - x += addHtmlValue('Features', addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1)); // Display user consent if (currentMesh.mtype == 2) { @@ -12271,20 +12330,18 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this } // Intel AMT setup - if (currentMesh.mtype == 2) { - var intelAmtPolicy = 'No Policy'; - if (currentMesh.amt) { - if (currentMesh.amt.type == 1) { intelAmtPolicy = 'Deactivate Client Control Mode (CCM)'; } - else if (currentMesh.amt.type == 2) { - intelAmtPolicy = 'Simple Client Control Mode (CCM)'; - if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } - } else if (currentMesh.amt.type == 3) { - intelAmtPolicy = 'Simple Admin Control Mode (ACM)'; - if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } - } + var intelAmtPolicy = 'No Policy'; + if (currentMesh.amt) { + if (currentMesh.amt.type == 1) { intelAmtPolicy = 'Deactivate Client Control Mode (CCM)'; } + else if (currentMesh.amt.type == 2) { + intelAmtPolicy = 'Simple Client Control Mode (CCM)'; + if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } + } else if (currentMesh.amt.type == 3) { + intelAmtPolicy = 'Simple Admin Control Mode (ACM)'; + if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } } - x += addHtmlValue('Intel® AMT', addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1)); } + x += addHtmlValue('Intel® AMT', addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1)); // Display group note support if (meshrights & 1) { x += '
'; } @@ -12297,6 +12354,11 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this if (currentMesh.mtype == 1) { x += ' Install CIRA'; x += ' Install local'; + if (currentMesh.amt && (currentMesh.amt.type == 2)) { // CCM activation + x += ' Activation'; + } else if (currentMesh.amt && (currentMesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation + x += ' Activation'; + } } if (currentMesh.mtype == 2) { x += ' Install'; @@ -12352,7 +12414,11 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this if (xxdialogMode) return; var x = '', acmoption = ''; if ((features & 0x100000) != 0) { acmoption = ''; } - x += addHtmlValue('Type', ''); + if (currentMesh.mtype == 1) { + x += addHtmlValue('Type', ''); + } else { + x += addHtmlValue('Type', ''); + } x += '
'; setDialogMode(2, "Intel® AMT Policy", 3, p20editMeshAmtEx, x); if (currentMesh.amt) { Q('dp20amtpolicy').value = currentMesh.amt.type; } @@ -12361,7 +12427,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this // Set the current Intel AMT policy if (currentMesh.amt && (currentMesh.amt.type == 2) || (currentMesh.amt.type == 3)) { Q('dp20amtpolicypass').value = currentMesh.amt.password; - if (currentMesh.amt.type == 2) { Q('dp20amtbadpass').value = currentMesh.amt.badpass; } + if ((currentMesh.amt.type == 2) && (currentMesh.amt.badpass != null)) { Q('dp20amtbadpass').value = currentMesh.amt.badpass; } if ((features & 0x400) == 0) { Q('dp20amtcira').value = currentMesh.amt.cirasetup; } } @@ -12371,9 +12437,9 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this function p20editMeshAmtChange() { var ptype = Q('dp20amtpolicy').value, x = ''; if (ptype >= 2) { - x = addHtmlValue('Password*', '') - x += addHtmlValue('Password*', '') - if (ptype == 2) { x += addHtmlValue('Password mismatch', ""); } + x = addHtmlValue('Password*', '') + x += addHtmlValue('Password*', '') + if ((ptype == 2) && (currentMesh.mtype == 2)) { x += addHtmlValue('Password mismatch', ""); } if ((features & 0x400) == 0) { if (ptype == 2) { x += addHtmlValue('CIRA', ""); @@ -12381,15 +12447,18 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this x += addHtmlValue('CIRA', ""); } } - x += '
* Recommanded, leave blank to assign a random password to each device.
'; - if (ptype == 2) { - x += 'This policy will not impact devices with Intel® AMT in ACM mode.
'; - x += 'This is not a secure policy as agents will be performing activation.'; - } else { - x += 'During activation, the agent will have access to admin password infomation.'; + x += '
* Leave blank to assign a random password to each device.
'; + if (currentMesh.mtype == 2) { + if (ptype == 2) { + x += 'This policy will not impact devices with Intel® AMT in ACM mode.
'; + x += 'This is not a secure policy as agents will be performing activation.'; + } else { + x += 'During activation, the agent will have access to admin password infomation.'; + } } } QH('dp20amtpolicydiv', x); + setTimeout(dp20amtValidatePolicy, 1); } function dp20amtValidatePolicy() { @@ -12404,7 +12473,8 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this function p20editMeshAmtEx() { var ptype = parseInt(Q('dp20amtpolicy').value), amtpolicy = { type: ptype }; if (ptype == 2) { - amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value, badpass: parseInt(Q('dp20amtbadpass').value) }; + amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value }; + if (currentMesh.mtype == 2) { amtpolicy.badpass = parseInt(Q('dp20amtbadpass').value); } if ((features & 0x400) == 0) { amtpolicy.cirasetup = parseInt(Q('dp20amtcira').value); } else { amtpolicy.cirasetup = 1; } } else if (ptype == 3) { amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value }; diff --git a/views/default-mobile-min.handlebars b/views/default-mobile-min.handlebars index e8054ea6..180b2d79 100644 --- a/views/default-mobile-min.handlebars +++ b/views/default-mobile-min.handlebars @@ -1 +1 @@ - {{{title}}}
{{{title}}}
{{{title2}}}
\ No newline at end of file + {{{title}}}
{{{title}}}
{{{title2}}}
\ No newline at end of file diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index b974072a..2792b435 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -943,11 +943,14 @@ } if (message.event.node.intelamt != null) { if (node.intelamt == null) node.intelamt = {}; + if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; } if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; } if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; } if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; } if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; } - if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; } + if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; } + if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; } + if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; } } node.namel = node.name.toLowerCase(); if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; } diff --git a/views/default.handlebars b/views/default.handlebars index 922fcc2f..56e7cf69 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1848,15 +1848,19 @@ } if (message.event.node.intelamt != null) { if (node.intelamt == null) node.intelamt = {}; + if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; } if (message.event.node.intelamt.host != null) { node.intelamt.user = message.event.node.intelamt.host; } if (message.event.node.intelamt.user != null) { node.intelamt.user = message.event.node.intelamt.user; } if (message.event.node.intelamt.tls != null) { node.intelamt.tls = message.event.node.intelamt.tls; } if (message.event.node.intelamt.ver != null) { node.intelamt.ver = message.event.node.intelamt.ver; } - if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; } + if (message.event.node.intelamt.tag != null) { node.intelamt.tag = message.event.node.intelamt.tag; } + if (message.event.node.intelamt.uuid != null) { node.intelamt.uuid = message.event.node.intelamt.uuid; } + if (message.event.node.intelamt.realm != null) { node.intelamt.realm = message.event.node.intelamt.realm; } } node.namel = node.name.toLowerCase(); if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; } if (message.event.node.icon) { node.icon = message.event.node.icon; } + console.log(node); // Web page update masterUpdate(2 | 4 | 8 | 16); @@ -2577,7 +2581,9 @@ r += ' Add Local'; r += ' Scan Network'; } - if ((features & 0x00100000) != 0) { // ACM activation + if (mesh.amt && (mesh.amt.type == 2)) { // CCM activation + r += ' Activation'; + } else if (mesh.amt && (mesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation r += ' Activation'; } } @@ -2602,7 +2608,25 @@ Q('dp1devicename').focus(); } - // Intel AMT Activation + // Intel AMT CCM Activation + function showCcmActivation(meshid) { + if (xxdialogMode) return; + var servername = serverinfo.name, mesh = meshes[meshid]; + if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name. + var url, domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1); + if (serverinfo.https == true) { + var portStr = (serverinfo.port == 443) ? '' : (":" + serverinfo.port); + url = "wss://" + servername + portStr + domainUrl; + } else { + var portStr = (serverinfo.port == 80) ? '' : (":" + serverinfo.port); + url = "ws://" + servername + portStr + domainUrl; + } + var x = "Perform Intel AMT client control mode (CCM) activation to group \"" + EscapeHtml(mesh.name) + "\" by downloading the MeshCMD tool and running it like this:

"; + x += ''; + setDialogMode(2, "Intel® AMT activation", 9, null, x); + } + + // Intel AMT ACM Activation function showAcmActivation(meshid) { if (xxdialogMode) return; var servername = serverinfo.name, mesh = meshes[meshid]; @@ -3856,11 +3880,20 @@ x += addDeviceAttribute('Intel® AMT', str); } - // Attribute: Mesh Agent Tag - if ((node.agent != null) && (node.agent.tag != null) && (node.agent.tag != 'mailto:')) { - var tag = EscapeHtml(node.agent.tag); - if (tag.startsWith('mailto:')) { tag = '' + tag.substring(7) + ''; } - x += addDeviceAttribute('Agent Tag', tag); + if (mesh.mtype == 2) { + // Attribute: Mesh Agent Tag + if ((node.agent != null) && (node.agent.tag != null)) { + var tag = EscapeHtml(node.agent.tag); + if (tag.startsWith('mailto:')) { tag = '' + tag.substring(7) + ''; } + x += addDeviceAttribute('Agent Tag', tag); + } + } else { + // Attribute: Intel AMT Tag + if ((node.intelamt != null) && (node.intelamt.tag != null)) { + var tag = EscapeHtml(node.intelamt.tag); + if (tag.startsWith('mailto:')) { tag = '' + tag.substring(7) + ''; } + x += addDeviceAttribute('Intel® AMT Tag', tag); + } } // Attribute: Intel AMT @@ -6213,14 +6246,16 @@ //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]); // Display features - var meshFeatures = []; - if (currentMesh.flags) { - if (currentMesh.flags & 1) { meshFeatures.push('Auto-Remove'); } - if (currentMesh.flags & 2) { meshFeatures.push('Hostname Sync'); } + if (currentMesh.mtype == 2) { + var meshFeatures = []; + if (currentMesh.flags) { + if (currentMesh.flags & 1) { meshFeatures.push('Auto-Remove'); } + if (currentMesh.flags & 2) { meshFeatures.push('Hostname Sync'); } + } + meshFeatures = meshFeatures.join(', '); + if (meshFeatures == '') { meshFeatures = 'None'; } + x += addHtmlValue('Features', addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1)); } - meshFeatures = meshFeatures.join(', '); - if (meshFeatures == '') { meshFeatures = 'None'; } - x += addHtmlValue('Features', addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1)); // Display user consent if (currentMesh.mtype == 2) { @@ -6240,20 +6275,18 @@ } // Intel AMT setup - if (currentMesh.mtype == 2) { - var intelAmtPolicy = 'No Policy'; - if (currentMesh.amt) { - if (currentMesh.amt.type == 1) { intelAmtPolicy = 'Deactivate Client Control Mode (CCM)'; } - else if (currentMesh.amt.type == 2) { - intelAmtPolicy = 'Simple Client Control Mode (CCM)'; - if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } - } else if (currentMesh.amt.type == 3) { - intelAmtPolicy = 'Simple Admin Control Mode (ACM)'; - if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } - } + var intelAmtPolicy = 'No Policy'; + if (currentMesh.amt) { + if (currentMesh.amt.type == 1) { intelAmtPolicy = 'Deactivate Client Control Mode (CCM)'; } + else if (currentMesh.amt.type == 2) { + intelAmtPolicy = 'Simple Client Control Mode (CCM)'; + if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } + } else if (currentMesh.amt.type == 3) { + intelAmtPolicy = 'Simple Admin Control Mode (ACM)'; + if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; } } - x += addHtmlValue('Intel® AMT', addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1)); } + x += addHtmlValue('Intel® AMT', addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1)); // Display group note support if (meshrights & 1) { x += '
'; } @@ -6266,6 +6299,11 @@ if (currentMesh.mtype == 1) { x += ' Install CIRA'; x += ' Install local'; + if (currentMesh.amt && (currentMesh.amt.type == 2)) { // CCM activation + x += ' Activation'; + } else if (currentMesh.amt && (currentMesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation + x += ' Activation'; + } } if (currentMesh.mtype == 2) { x += ' Install'; @@ -6321,7 +6359,11 @@ if (xxdialogMode) return; var x = '', acmoption = ''; if ((features & 0x100000) != 0) { acmoption = ''; } - x += addHtmlValue('Type', ''); + if (currentMesh.mtype == 1) { + x += addHtmlValue('Type', ''); + } else { + x += addHtmlValue('Type', ''); + } x += '
'; setDialogMode(2, "Intel® AMT Policy", 3, p20editMeshAmtEx, x); if (currentMesh.amt) { Q('dp20amtpolicy').value = currentMesh.amt.type; } @@ -6330,7 +6372,7 @@ // Set the current Intel AMT policy if (currentMesh.amt && (currentMesh.amt.type == 2) || (currentMesh.amt.type == 3)) { Q('dp20amtpolicypass').value = currentMesh.amt.password; - if (currentMesh.amt.type == 2) { Q('dp20amtbadpass').value = currentMesh.amt.badpass; } + if ((currentMesh.amt.type == 2) && (currentMesh.amt.badpass != null)) { Q('dp20amtbadpass').value = currentMesh.amt.badpass; } if ((features & 0x400) == 0) { Q('dp20amtcira').value = currentMesh.amt.cirasetup; } } @@ -6340,9 +6382,9 @@ function p20editMeshAmtChange() { var ptype = Q('dp20amtpolicy').value, x = ''; if (ptype >= 2) { - x = addHtmlValue('Password*', '') - x += addHtmlValue('Password*', '') - if (ptype == 2) { x += addHtmlValue('Password mismatch', ""); } + x = addHtmlValue('Password*', '') + x += addHtmlValue('Password*', '') + if ((ptype == 2) && (currentMesh.mtype == 2)) { x += addHtmlValue('Password mismatch', ""); } if ((features & 0x400) == 0) { if (ptype == 2) { x += addHtmlValue('CIRA', ""); @@ -6350,15 +6392,18 @@ x += addHtmlValue('CIRA', ""); } } - x += '
* Recommanded, leave blank to assign a random password to each device.
'; - if (ptype == 2) { - x += 'This policy will not impact devices with Intel® AMT in ACM mode.
'; - x += 'This is not a secure policy as agents will be performing activation.'; - } else { - x += 'During activation, the agent will have access to admin password infomation.'; + x += '
* Leave blank to assign a random password to each device.
'; + if (currentMesh.mtype == 2) { + if (ptype == 2) { + x += 'This policy will not impact devices with Intel® AMT in ACM mode.
'; + x += 'This is not a secure policy as agents will be performing activation.'; + } else { + x += 'During activation, the agent will have access to admin password infomation.'; + } } } QH('dp20amtpolicydiv', x); + setTimeout(dp20amtValidatePolicy, 1); } function dp20amtValidatePolicy() { @@ -6373,7 +6418,8 @@ function p20editMeshAmtEx() { var ptype = parseInt(Q('dp20amtpolicy').value), amtpolicy = { type: ptype }; if (ptype == 2) { - amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value, badpass: parseInt(Q('dp20amtbadpass').value) }; + amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value }; + if (currentMesh.mtype == 2) { amtpolicy.badpass = parseInt(Q('dp20amtbadpass').value); } if ((features & 0x400) == 0) { amtpolicy.cirasetup = parseInt(Q('dp20amtcira').value); } else { amtpolicy.cirasetup = 1; } } else if (ptype == 3) { amtpolicy = { type: ptype, password: Q('dp20amtpolicypass').value }; diff --git a/webserver.js b/webserver.js index 3bf12629..6168ec71 100644 --- a/webserver.js +++ b/webserver.js @@ -1554,7 +1554,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Returns the mesh server root certificate function handleRootCertRequest(req, res) { if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { return; } // Check server-wide IP filter only. - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + certificates.RootName + '.cer"' }); + try { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + certificates.RootName + '.cer"' }); + } catch (ex) { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="rootcert.cer"' }); + } res.send(Buffer.from(getRootCertBase64(), 'base64')); } @@ -1662,7 +1666,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { try { stat = obj.fs.statSync(path); } catch (e) { } if ((stat != null) && ((stat.mode & 0x004000) == 0)) { if (req.query.download == 1) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' }); + try { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' }); + } catch (ex) { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"file.bin\"' }); + } try { res.sendFile(obj.path.resolve(__dirname, path)); } catch (e) { res.sendStatus(404); } } else { res.render(obj.path.join(obj.parent.webViewsPath, 'download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, domainurl: domain.url, message: "" + filename + ", " + stat.size + " byte" + ((stat.size < 2) ? '' : 's') + "." }); @@ -1773,7 +1781,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (user == null) { res.sendStatus(404); return; } const file = obj.getServerFilePath(user, domain, req.query.link); if (file == null) { res.sendStatus(404); return; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + file.name + '\"' }); + try { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + file.name + '\"' }); + } catch (ex) { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"file.bin\"' }); + } try { res.sendFile(file.fullpath); } catch (e) { res.sendStatus(404); } } @@ -2166,8 +2178,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (mesh.mtype != 1) { ws.send(JSON.stringify({ errorText: 'Invalid device group type' })); ws.close(); return; } // Fetch the remote IP:Port for logging - const remoteaddr = (req.ip.startsWith('::ffff:')) ? (req.ip.substring(7)) : req.ip; - ws.remoteaddrport = remoteaddr + ':' + ws._socket.remotePort; + ws.remoteaddr = (req.ip.startsWith('::ffff:')) ? (req.ip.substring(7)) : req.ip; + ws.remoteaddrport = ws.remoteaddr + ':' + ws._socket.remotePort; // When data is received from the web socket, echo it back ws.on('message', function (data) { @@ -2178,11 +2190,37 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Process the command switch (cmd.action) { + case 'ccmactivate': { + // Check the command + if (cmd.version != 1) { ws.send(JSON.stringify({ errorText: 'Unsupported version' })); ws.close(); return; } + if (obj.common.validateString(cmd.realm, 16, 256) == false) { ws.send(JSON.stringify({ errorText: 'Invalid realm argument' })); ws.close(); return; } + if (obj.common.validateString(cmd.uuid, 36, 36) == false) { ws.send(JSON.stringify({ errorText: 'Invalid UUID argument' })); ws.close(); return; } + if ((obj.common.validateString(cmd.ver, 5, 16) == false) || (cmd.ver.split('.').length != 3)) { ws.send(JSON.stringify({ errorText: 'Invalid Intel AMT version' })); ws.close(); return; } + + // Get the current Intel AMT policy + var mesh = obj.meshes[ws.meshid]; + if ((mesh == null) || (mesh.amt == null) || (mesh.amt.type != 2) || (mesh.amt.password == null)) { ws.send(JSON.stringify({ errorText: 'Unable to activate' })); ws.close(); return; } + + // Get the Intel AMT admin password, randomize if needed. + var amtpassword = ((mesh.amt.password == '') ? getRandomAmtPassword() : mesh.amt.password); + if (checkAmtPassword(amtpassword) == false) { ws.send(JSON.stringify({ errorText: 'Invalid Intel AMT password' })); ws.close(); return; } // Invalid Intel AMT password, this should never happen. + + // Log the activation request, logging is a required step for activation. + if (parent.certificateOperations.logAmtActivation(domain, { time: new Date(), action: 'ccmactivate', domain: domain.id, amtUuid: cmd.uuid, amtRealm: cmd.realm, user: 'admin', password: amtpassword, ipport: ws.remoteaddrport, meshid: ws.meshid, tag: cmd.tag, name: cmd.name }) == false) return { errorText: 'Unable to log operation' }; + + // Save some state, if activation is succesful, we need this to add the device + ws.xxstate = { uuid: cmd.uuid, realm: cmd.realm, tag: cmd.tag, name: cmd.name, pass: amtpassword, flags: 2, ver: cmd.ver }; // Flags 2 = CCM + + // Compute the HTTP digest hash and send the response + ws.send(JSON.stringify({ action: 'ccmactivate', password: obj.crypto.createHash('md5').update('admin:' + cmd.realm + ':' + amtpassword).digest('hex') })); + break; + } case 'acmactivate': { // Check the command if (cmd.version != 1) { ws.send(JSON.stringify({ errorText: 'Unsupported version' })); ws.close(); return; } if (typeof cmd.hashes != 'object') { ws.send(JSON.stringify({ errorText: 'Invalid hashes' })); ws.close(); return; } if (typeof cmd.fqdn != 'string') { ws.send(JSON.stringify({ errorText: 'Invalid FQDN' })); ws.close(); return; } + if ((obj.common.validateString(cmd.ver, 5, 16) == false) || (cmd.ver.split('.').length != 3)) { ws.send(JSON.stringify({ errorText: 'Invalid Intel AMT version' })); ws.close(); return; } // Get the current Intel AMT policy var mesh = obj.meshes[ws.meshid]; @@ -2213,9 +2251,67 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var amtpassword = ((mesh.amt.password == '') ? getRandomAmtPassword() : mesh.amt.password); if (checkAmtPassword(amtpassword) == false) { ws.send(JSON.stringify({ errorText: 'Invalid Intel AMT password' })); ws.close(); return; } // Invalid Intel AMT password, this should never happen. + // Save some state, if activation is succesful, we need this to add the device + ws.xxstate = { uuid: cmd.uuid, realm: cmd.realm, tag: cmd.tag, name: cmd.name, pass: amtpassword, flags: 4, ver: cmd.ver }; // Flags 4 = ACM + // Agent is asking the server to sign an Intel AMT ACM activation request var signResponse = parent.certificateOperations.signAcmRequest(domain, cmd, 'admin', amtpassword, ws.remoteaddrport, null, ws.meshid, null, null); - //ws.send(JSON.stringify(signResponse)); // DEBUG*************************** + ws.send(JSON.stringify(signResponse)); + break; + } + case 'ccmactivate-failed': + case 'acmactivate-failed': { + // Log the activation response + parent.certificateOperations.logAmtActivation(domain, { time: new Date(), action: cmd.action, domain: domain.id, amtUuid: cmd.uuid, ipport: ws.remoteaddrport, meshid: ws.meshid }); + break; + } + case 'ccmactivate-success': + case 'acmactivate-success': { + // Log the activation response + parent.certificateOperations.logAmtActivation(domain, { time: new Date(), action: cmd.action, domain: domain.id, amtUuid: cmd.uuid, ipport: ws.remoteaddrport, meshid: ws.meshid }); + + // Get the current Intel AMT policy + var mesh = obj.meshes[ws.meshid]; + if (mesh == null) { ws.send(JSON.stringify({ errorText: 'Unknown device group' })); ws.close(); return; } + + // Fix the computer name if needed + if ((ws.xxstate.name == null) || (ws.xxstate.name.length == 0)) { ws.xxstate.name = ws.xxstate.uuid; } + + db.getAmtUuidNode(ws.meshid, ws.xxstate.uuid, function (err, nodes) { + if ((nodes == null) || (nodes.length == 0)) { + // Create a new nodeid + parent.crypto.randomBytes(48, function (err, buf) { + // Create the new node + var xxnodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); + var device = { type: 'node', _id: xxnodeid, meshid: ws.meshid, name: ws.xxstate.name, host: ws.remoteaddr, domain: domain.id, intelamt: { state: 2, flags: ws.xxstate.flags, user: 'admin', pass: ws.xxstate.pass, tls: 0, uuid: ws.xxstate.uuid, realm: ws.xxstate.realm, tag: ws.xxstate.tag, ver: ws.xxstate.ver } }; + db.Set(device); + + // Event the new node + var device2 = obj.common.Clone(device); + delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + parent.DispatchEvent(['*', ws.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: 'Added device ' + ws.xxstate.name + ' to mesh ' + mesh.name, domain: domain.id }); + }); + } else { + // Change an existing device + var device = nodes[0]; + if (device.host != ws.remoteaddr) { device.host = ws.remoteaddr; } + if (device.intelamt.state != 2) { device.intelamt.state = 2; } + if (device.intelamt.flags != ws.xxstate.flags) { device.intelamt.state = ws.xxstate.flags; } + if (device.intelamt.user != 'admin') { device.intelamt.user = 'admin'; } + if (device.intelamt.pass != ws.xxstate.pass) { device.intelamt.pass = ws.xxstate.pass; } + if (device.intelamt.realm != ws.xxstate.realm) { device.intelamt.realm = ws.xxstate.realm; } + if (ws.xxstate.realm == null) { delete device.intelamt.tag; } + else if (device.intelamt.tag != ws.xxstate.tag) { device.intelamt.tag = ws.xxstate.tag; } + if (device.intelamt.ver != ws.xxstate.ver) { device.intelamt.ver = ws.xxstate.ver; } + db.Set(device); + + // Event the new node + var device2 = obj.common.Clone(device); + delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. + parent.DispatchEvent(['*', ws.meshid], obj, { etype: 'node', action: 'changenode', nodeid: device2._id, node: device2, msg: 'Changed device ' + device.name + ' in mesh ' + mesh.name, domain: domain.id }); + } + }); break; } default: { @@ -2448,7 +2544,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.args.agentconfig) { for (var i in obj.args.agentconfig) { meshsettings += obj.args.agentconfig[i] + "\r\n"; } } if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + "\r\n"; } } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + meshfilename + '"' }); + try { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + meshfilename + '"' }); + } catch (ex) { + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); + } obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe }); } } else if (req.query.script != null) {