New MeshCmd, fixes MeshAgent registry values

Ylian Saint-Hilaire committed Apr 4, 2018 at 12:08 UTC 835e03225d1edb916f3cbbd20a163abdca3a93ac
10 files changed +142 -279
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService.exe
Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/MeshService64.exe
Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ
agents/meshcmd.js
+43 -71
@@ -84,15 +84,14 @@ function objToString(x, p, ret) {
84 function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ' '; } return r; }
85
86 // Parse the incoming arguments
87 -function run(argv)
88 -{
87 +function run(argv) {
88 if (meshCmdVersion[0] == '*') { meshCmdVersion = ''; } else { meshCmdVersion = ' v' + meshCmdVersion; }
89 var args = parceArguments(argv);
90 //console.log(JSON.stringify(argv));
91 //console.log('addedModules = ' + JSON.stringify(addedModules));
92 var actionpath = 'meshaction.txt';
93 if (args.actionfile != null) { actionpath = args.actionfile; }
95 - var actions = ['HELP', 'ROUTE', 'AMTLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG'];
94 + var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG'];
95
96 // Load the action file
97 var actionfile = null;
@@ -134,10 +133,10 @@ function run(argv)
133 console.log('\r\nValid local actions:');
134 console.log(' SMBios - Display System Management BIOS tables for this computer.');
135 console.log(' RawSMBios - Display RAW System Management BIOS tables for this computer.');
136 + console.log(' MicroLMS - Run MicroLMS, allowing local access to Intel AMT.');
137 console.log(' AmtInfo - Show Intel AMT version and activation state.');
138 console.log(' AmtVersions - Show all Intel ME version information.');
139 console.log(' AmtHashes - Show all Intel AMT trusted activation hashes.');
140 - console.log(' AmtLMS - Run MicroLMS, allowing local access to Intel AMT.');
140 console.log(' AmtCCM - Activate Intel AMT into Client Control Mode.');
141 console.log(' AmtDeactivate - Deactivate Intel AMT if activated in Client Control mode.');
142 console.log('\r\nValid local or remote actions:');
@@ -176,10 +175,12 @@ function run(argv)
175 console.log('AmtVersions will display all version information about Intel AMT on this computer. The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Example usage:\r\n\r\n meshcmd amtversions');
176 } else if (action == 'amthashes') {
177 console.log('Amthashes will display all trusted activations hashes for Intel AMT on this computer. The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. These certificates hashes are used by Intel AMT when performing activation into ACM mode. Example usage:\r\n\r\n meshcmd amthashes');
179 - } else if (action == 'amtlms') {
180 - console.log('AmtLMS will state MicroLMS on this computer, allowing local access to Intel AMT on TCP ports 16992 and 16993 when applicable. The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. These certificates hashes are used by Intel AMT when performing activation into ACM mode. Example usage:\r\n\r\n meshcmd amtlms');
178 + } else if ((action == 'microlms') || (action == 'lms') || (action == 'amtlms')) {
179 + console.log('Starts MicroLMS on this computer, allowing local access to Intel AMT on TCP ports 16992 and 16993 when applicable. The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. These certificates hashes are used by Intel AMT when performing activation into ACM mode. Example usage:\r\n\r\n meshcmd microlms');
180 console.log('\r\nPossible arguments:\r\n');
181 console.log(' --noconsole MeshCommander for LMS will no be available on port 16994.');
182 + console.log('\r\nRun as a background service:\r\n');
183 + console.log(' microlms install/uninstall/start/stop.');
184 } else if (action == 'amtccm') {
185 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');
186 } else if (action == 'amtdeactivate') {
@@ -232,6 +233,8 @@ function run(argv)
233 console.log('This action launched a local web server that hosts MeshCommander, a Intel AMT management console.');
234 console.log('\r\nPossible arguments:\r\n');
235 console.log(' --localport [port] Local port used for the web server, 3000 is default.');
236 + console.log('\r\nRun as a background service:\r\n');
237 + console.log(' meshcommander install/uninstall/start/stop.');
238 } else if (action == 'amtauditlog') {
239 console.log('AmtAuditLog action will fetch the local or remote audit log. If used localy, no username/password is required. Example usage:\r\n\r\n meshcmd amtauditlog --host 1.2.3.4 --user admin --pass mypassword --tls --output audit.json');
240 console.log('\r\nPossible arguments:\r\n');
@@ -342,7 +345,7 @@ function run(argv)
345 else if (mestate.ProvisioningState.stateStr == 'POST') { if (mestate.ProvisioningMode.modeStr == 'ENTERPRISE') { str += ', activated in ' + ["none", "client control mode", "admin control mode", "remote assistance mode"][mestate.controlmode.controlMode]; } else { str += ', activated in ' + mestate.ProvisioningMode.modeStr; } }
346 if (mestate.ehbc.EHBC == true) { str += ', EHBC enabled'; }
347 str += '.';
345 - if (mestate.net0 != null) { str += '\r\nWired ' + ((mestate.net0.enabled == 1) ? 'Enabled' : 'Disabled') + ((mestate.net0.dhcpEnabled == 1) ? ', DHCP' : ', Static') + ', ' + mestate.net0.mac + (mestate.net0.address == '0.0.0.0'?'':(', ' + mestate.net0.address)); }
348 + if (mestate.net0 != null) { str += '\r\nWired ' + ((mestate.net0.enabled == 1) ? 'Enabled' : 'Disabled') + ((mestate.net0.dhcpEnabled == 1) ? ', DHCP' : ', Static') + ', ' + mestate.net0.mac + (mestate.net0.address == '0.0.0.0' ? '' : (', ' + mestate.net0.address)); }
349 if (mestate.net1 != null) { str += '\r\nWireless ' + ((mestate.net1.enabled == 1) ? 'Enabled' : 'Disabled') + ((mestate.net1.dhcpEnabled == 1) ? ', DHCP' : ', Static') + ', ' + mestate.net1.mac + (mestate.net1.address == '0.0.0.0' ? '' : (', ' + mestate.net1.address)); }
350 console.log(str + '.');
351 exit(1);
@@ -357,10 +360,10 @@ function run(argv)
360 settings.localport = 16992;
361 debug(1, "Settings: " + JSON.stringify(settings));
362 saveEntireAmtState();
360 - } else if (settings.action == 'amtlms') {
363 + } else if ((settings.action == 'microlms') || (settings.action == 'amtlms') || (settings.action == 'lms')) {
364 // Start Intel AMT MicroLMS
365 startLms(function (state) {
363 - console.log(['MicroLMS did not start. MicroLMS must run as administrator or LMS any already be active.', 'MicroLMS started.', 'MicroLMS started, MeshCommander on HTTP/16994.', 'MEI error'][state]); console.log('Press ctrl-c to exit.'); if (state == 0) { exit(0); }
366 + console.log(['MicroLMS did not start. Must run as administrator or LMS already active.', 'MicroLMS started.', 'MicroLMS started, MeshCommander on HTTP/16994.', 'MEI error'][state]); console.log('Press ctrl-c to exit.'); if (state == 0) { exit(0); }
367 });
368 } else if (settings.action == 'amtscript') {
369 // Start running a MEScript
@@ -436,7 +439,7 @@ function readAmtAuditLogEx2(stack, response, status) {
439 } else {
440 var out = '';
441 for (var i in response) {
439 - var name = ((response[i].Initiator != '')?(response[i].Initiator + ': '):'')
442 + var name = ((response[i].Initiator != '') ? (response[i].Initiator + ': ') : '')
443 out += (response[i].Time + ' - ' + name + response[i].Event + '\r\n');
444 }
445 if (settings.output == null) { console.log(out); } else { var file = fs.openSync(settings.output, 'w'); fs.writeSync(file, new Buffer(out, 'utf8')); fs.closeSync(file); }
@@ -559,7 +562,7 @@ function activeToCCMEx(state) {
562 function activeToCCMEx2(stack, name, responses, status) {
563 if (status != 200) { console.log('Failed to fetch activation status, status ' + status); exit(1); }
564 else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) { console.log('Client control mode activation not allowed'); exit(1); }
562 - else { osamtstack.IPS_HostBasedSetupService_Setup(2, md5hex('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + settings.password).substring(0,32), null, null, null, null, activeToCCMEx3); }
565 + else { osamtstack.IPS_HostBasedSetupService_Setup(2, md5hex('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + settings.password).substring(0, 32), null, null, null, null, activeToCCMEx3); }
566 }
567
568 function activeToCCMEx3(stack, name, responses, status) {
@@ -624,7 +627,7 @@ function startMeScriptEx() {
627 try { scriptData = fs.readFileSync(settings.script); } catch (e) { console.log('Unable to read script file (1): ' + settings.script + '.'); exit(1); return; }
628 } else {
629 scriptData = settings.scriptJSON;
627 - }
630 + }
631 if (scriptData == null) { console.log('Unable to read script file (2): ' + settings.script + '.'); exit(1); return; }
632 try { scriptData = JSON.parse(scriptData); } catch (e) { console.log('Unable to read script file (3): ' + settings.script + '.'); exit(1); return; }
633 if (scriptData.mescript == null) { console.log('Unable to read script file (4): ' + settings.script + '.'); exit(1); return; }
@@ -634,7 +637,7 @@ function startMeScriptEx() {
637 var script = scriptModule.setup(scriptData, {})
638 script.amtstack = amtstack;
639 script.start();
637 - script.onCompleted = function () { exit(1);}
640 + script.onCompleted = function () { exit(1); }
641 }
642
643
@@ -651,7 +654,7 @@ function saveEntireAmtState() {
654 var transport = require('amt-wsman-duk');
655 var wsman = require('amt-wsman');
656 var amt = require('amt');
654 - wsstack = new wsman(transport, settings.hostname, settings.tls?16993:16992, settings.username, settings.password, settings.tls);
657 + wsstack = new wsman(transport, settings.hostname, settings.tls ? 16993 : 16992, settings.username, settings.password, settings.tls);
658 amtstack = new amt(wsstack);
659 amtstack.onProcessChanged = onWsmanProcessChanged;
660 //var AllWsman = "AMT_GeneralSystemDefenseCapabilities".split(',');
@@ -769,7 +772,6 @@ function startLms(func) {
772 amtLms = new lme_heci({ debug: settings.lmsdebug });
773 amtLms.on('error', function (e) {
774 console.log('LME connection failed', e);
772 -
775 setupMeiOsAdmin(func, amtLms.connected == false ? 0 : 3);
776 });
777 amtLms.on('notify', function (data, options, str, code) {
@@ -843,7 +845,7 @@ function startLms(func) {
845 tempTimer = setTimeout(function () { delete tempTimer; setupMeiOsAdmin(func, 1); }, 100);
846 //console.logReferenceCount(tempTimer);
847 }
846 -
848 +
849 });
850 }
851
@@ -957,7 +959,7 @@ function processLmsControlData(data) {
959 case 2: // Intel AMT MEI Unprovision (CMD = 2)
960 { if (data.length < 6) break; amtMei.unprovision(data.readUInt32LE(2), function (status, socket) { var data = new Buffer(6); data.writeUInt16LE(2, 0); data.writeUInt32LE(status, 2); socket.write(data); }, this); break; }
961 case 3: // Intel AMT MEI GetLocalSystemAccount (CMD = 3)
960 - { amtMei.getLocalSystemAccount(function (account, socket) {socket.write(Buffer.concat([Buffer.from('030000000000', 'hex'), account.raw])); }, this); break; }
962 + { amtMei.getLocalSystemAccount(function (account, socket) { socket.write(Buffer.concat([Buffer.from('030000000000', 'hex'), account.raw])); }, this); break; }
963 case 4: // Instruct Intel AMT to start remote configuration (CMD = 4)
964 { amtMei.startConfiguration(function (status, socket) { var data = new Buffer(6); data.writeUInt16LE(7, 0); data.writeUInt32LE(status, 2); socket.write(data); }, this); break; }
965 case 5: // Instruct Intel AMT to stop remote configuration (CMD = 5)
@@ -1150,7 +1152,7 @@ function getAmtStorage(func, noretry) {
1152 // Fetch the Intel AMT storage document
1153 function pushToStorage(name, linkname, data, func, ptr) {
1154 if (ptr == null) { ptr = 0; }
1153 - var req = digest.request({ protocol: settings.protocol, method: "PUT", host: settings.hostname, path: ("/amt-storage/" + name + ((ptr != 0) ? '?append=' : '')), port: settings.localport } );
1155 + var req = digest.request({ protocol: settings.protocol, method: "PUT", host: settings.hostname, path: ("/amt-storage/" + name + ((ptr != 0) ? '?append=' : '')), port: settings.localport });
1156 req.on('error', function (e) { console.log("Error occured: " + JSON.stringify(e)); if (func != null) { func(null); } });
1157 req.on('response', function (response) {
1158 debug(1, 'Chunk Done', data.length, ptr);
@@ -1178,7 +1180,7 @@ function verifyStorage(name, data, func) {
1180
1181 // Fetch the Intel AMT storage document
1182 function deleteStorage(name, func, noretry) {
1181 - var req = digest.request({ protocol: settings.protocol, method: "DELETE", host: settings.hostname, path: "/amt-storage/" + name, port: settings.localport } );
1183 + var req = digest.request({ protocol: settings.protocol, method: "DELETE", host: settings.hostname, path: "/amt-storage/" + name, port: settings.localport });
1184 req.on('error', function (e) { if ((e == 'Error: Socket was unexpectedly closed') && (noretry != true)) { deleteStorage(name, func, true); } else { if (func != null) { if (e.statusCode) { func(e.statusCode); } else { func(null); } } } });
1185 req.on('response', function (response) { if (func != null) { func(response.statusCode); } });
1186 req.end();
@@ -1203,69 +1205,39 @@ function removeItemFromArray(array, element) {
1205 var serviceName = null;
1206 var serviceOpSpecified = 0;
1207
1206 -for (var i in process.argv)
1207 -{
1208 - if(process.argv[i].toLowerCase() == 'amtlms')
1209 - {
1210 - serviceName = 'MeshCmd_Lms';
1211 - break;
1212 - }
1213 - if(process.argv[i].toLowerCase() == 'meshcommander')
1214 - {
1215 - serviceName = 'MeshCmd_Commander';
1216 - break;
1217 - }
1208 +for (var i in process.argv) {
1209 + if ((process.argv[i].toLowerCase() == 'microlms') || (process.argv[i].toLowerCase() == 'amtlms') || (process.argv[i].toLowerCase() == 'lms')) { serviceName = 'MicroLMS'; break; }
1210 + if ((process.argv[i].toLowerCase() == 'meshcommander') || (process.argv[i].toLowerCase() == 'commander')) { serviceName = 'MeshCommander'; break; }
1211 }
1212
1220 -if (serviceName == null)
1221 -{
1222 - for (var i in process.argv)
1223 - {
1224 - if (process.argv[i] == '-install' || process.argv[i] == '-uninstall')
1225 - {
1226 - console.log('In order to Install/Uninstall, a service type must be specified');
1213 +if (serviceName == null) {
1214 + for (var i in process.argv) {
1215 + if ((process.argv[i].toLowerCase() == 'install') || (process.argv[i].toLowerCase() == 'uninstall')) {
1216 + console.log('In order to install/uninstall, a service type must be specified.');
1217 process.exit();
1218 }
1219 }
1230 - if(process.execPath.includes('MeshCmd_Lms'))
1231 - {
1232 - serviceName = 'MeshCmd_Lms';
1233 - }
1234 - else if(process.execPath.includes('MeshCmd_Commander'))
1235 - {
1236 - serviceName = 'MeshCmd_Commander';
1237 - }
1238 - else
1239 - {
1240 - serviceName = 'not_a_service';
1241 - }
1220 + if (process.execPath.includes('MicroLMS')) { serviceName = 'MicroLMS'; }
1221 + else if (process.execPath.includes('MeshCommander')) { serviceName = 'MeshCommander'; }
1222 + else { serviceName = 'not_a_service'; }
1223 }
1224
1225 var serviceHost = require('serviceHost');
1226 var meshcmdService = new serviceHost({ name: serviceName, startType: 'AUTO_START' });
1246 -meshcmdService.on('serviceStart', function onStart()
1247 -{
1248 - console.setDestination(console.Destinations.LOGFILE);
1249 - if (process.execPath.includes('MeshCmd_Lms'))
1250 - {
1251 - run([process.execPath, 'AmtLms']);
1252 - }
1253 - else if(process.execPath.includes('MeshCmd_Commander'))
1254 - {
1255 - run([process.execPath, 'MeshCommander']);
1256 - }
1257 - else
1258 - {
1259 - console.log('Aborting Service Start, because unknown binary: ' + process.execPath);
1260 - process.exit(1);
1261 - }
1262 -});
1263 -meshcmdService.on('serviceStop', function onStop() { console.log('LMS Stopping'); process.exit(); });
1264 -meshcmdService.on('normalStart', function onNormalStart()
1265 -{
1266 - try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); }
1227 +
1228 +// Called when the background service is started.
1229 +meshcmdService.on('serviceStart', function onStart() {
1230 + console.setDestination(console.Destinations.DISABLED); // Disable console.log().
1231 + if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } //
1232 + else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); }
1233 + else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
1234 });
1235
1236 +// Called when the background service is stopping
1237 +meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
1238 +
1239 +// Called when the executable is not running as a service, run normally.
1240 +meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
1241 meshcmdService.run();
1242
1243
agents/modules_meshcmd/serviceHost.js
+54 -116
@@ -1,22 +1,20 @@
1
2 var SERVICE_WIN32 = 0x00000010 | 0x00000020;
3 var SERVICE_STATE = { STOPPED: 0x00000001, SERVICE_START_PENDING: 0x00000002, SERVICE_STOP_PENDING: 0x00000003, RUNNING: 0x00000004 };
4 -var SERVICE_ACCEPT = {SERVICE_ACCEPT_STOP: 0x00000001, SERVICE_ACCEPT_SHUTDOWN: 0x00000004};
5 -var SERVICE_CONTROL = {SERVICE_CONTROL_SHUTDOWN: 0x00000005, SERVICE_CONTROL_STOP: 0x00000001};
4 +var SERVICE_ACCEPT = { SERVICE_ACCEPT_STOP: 0x00000001, SERVICE_ACCEPT_SHUTDOWN: 0x00000004 };
5 +var SERVICE_CONTROL = { SERVICE_CONTROL_SHUTDOWN: 0x00000005, SERVICE_CONTROL_STOP: 0x00000001 };
6 var NO_ERROR = 0;
7
8 var serviceManager = require('serviceManager');
9
10 -function serviceHost(serviceName)
11 -{
10 +function serviceHost(serviceName) {
11 this._ObjectID = 'serviceHost';
12 var emitterUtils = require('events').inherits(this);
13 emitterUtils.createEvent('serviceStart');
14 emitterUtils.createEvent('serviceStop');
15 emitterUtils.createEvent('normalStart');
16
18 - if (process.platform == 'win32')
19 - {
17 + if (process.platform == 'win32') {
18 this.GM = require('_GenericMarshal');
19 this.Advapi = this.GM.CreateNativeProxy('Advapi32.dll');
20 this.Advapi.CreateMethod({ method: 'StartServiceCtrlDispatcherA', threadDispatch: 1 });
@@ -33,8 +31,7 @@ function serviceHost(serviceName)
31 this._ServiceMain = this.GM.GetGenericGlobalCallback(2);
32 this._ServiceMain.Parent = this;
33 this._ServiceMain.GM = this.GM;
36 - this._ServiceMain.on('GlobalCallback', function onGlobalCallback(argc, argv)
37 - {
34 + this._ServiceMain.on('GlobalCallback', function onGlobalCallback(argc, argv) {
35 //ToDo: Check to make sure this is for us
36
37 this.Parent._ServiceStatus = this.GM.CreateVariable(28);
@@ -52,8 +49,7 @@ function serviceHost(serviceName)
49 this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_WIN32);
50 this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.SERVICE_STOPPED, 4);
51 this.Parent._ServiceStatusHandle = this.Parent.Advapi.RegisterServiceCtrlHandlerA(this.Parent._ServiceName, this.Parent._ServiceControlHandler);
55 - if(this.Parent._ServiceStatusHandle.Val == 0)
56 - {
52 + if (this.Parent._ServiceStatusHandle.Val == 0) {
53 process.exit(1);
54 }
55
@@ -67,8 +63,7 @@ function serviceHost(serviceName)
63 this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
64
65 this.Parent.Ole32.CoInitializeEx(0, 2);
70 - this.Parent.on('~', function OnServiceHostFinalizer()
71 - {
66 + this.Parent.on('~', function OnServiceHostFinalizer() {
67 var GM = require('_GenericMarshal');
68 var Advapi = GM.CreateNativeProxy('Advapi32.dll');
69 Advapi.CreateMethod('SetServiceStatus');
@@ -92,10 +87,8 @@ function serviceHost(serviceName)
87 this._ServiceControlHandler = this.GM.GetGenericGlobalCallback(1);
88 this._ServiceControlHandler.Parent = this;
89 this._ServiceControlHandler.GM = this.GM;
95 - this._ServiceControlHandler.on('GlobalCallback', function onServiceControlHandler(code)
96 - {
97 - switch (code.Val)
98 - {
90 + this._ServiceControlHandler.on('GlobalCallback', function onServiceControlHandler(code) {
91 + switch (code.Val) {
92 case SERVICE_CONTROL.SERVICE_CONTROL_SHUTDOWN:
93 case SERVICE_CONTROL.SERVICE_CONTROL_STOP:
94 this.Parent.emit('serviceStop');
@@ -113,54 +106,42 @@ function serviceHost(serviceName)
106 {
107 throw ('Must specify either ServiceName or Options');
108 }
116 - if (!this._ServiceOptions.servicePath)
117 - {
109 + if (!this._ServiceOptions.servicePath) {
110 this._ServiceOptions.servicePath = process.execPath;
111 }
120 -
121 - this.run = function run()
122 - {
112 +
113 + this.run = function run() {
114 var serviceOperation = 0;
115
125 - for(var i = 0; i<process.argv.length; ++i)
126 - {
127 - switch(process.argv[i])
128 - {
129 - case '-install':
116 + for (var i = 0; i < process.argv.length; ++i) {
117 + switch (process.argv[i].toLowerCase()) {
118 + case 'install':
119 if (!this._svcManager) { this._svcManager = new serviceManager(); }
131 - try
132 - {
120 + try {
121 this._svcManager.installService(this._ServiceOptions);
134 - }
135 - catch(e)
136 - {
122 + } catch (e) {
123 console.log(e);
124 process.exit();
125 }
140 - if (process.platform == 'win32')
141 - {
126 + if (process.platform == 'win32') {
127 // Only do this on Windows, becuase Linux is async... It'll complete later
143 - console.log(this._ServiceOptions.name + ' installed');
128 + console.log(this._ServiceOptions.name + ' installed.');
129 process.exit();
130 }
131 i = process.argv.length;
132 serviceOperation = 1;
133 break;
149 - case '-uninstall':
134 + case 'uninstall':
135 if (!this._svcManager) { this._svcManager = new serviceManager(); }
151 - try
152 - {
136 + try {
137 this._svcManager.uninstallService(this._ServiceOptions);
154 - }
155 - catch(e)
156 - {
138 + } catch (e) {
139 console.log(e);
140 process.exit();
141 }
160 - if (process.platform == 'win32')
161 - {
142 + if (process.platform == 'win32') {
143 // Only do this on Windows, becuase Linux is async... It'll complete later
163 - console.log(this._ServiceOptions.name + ' uninstalled');
144 + console.log(this._ServiceOptions.name + ' uninstalled.');
145 process.exit();
146 }
147 i = process.argv.length;
@@ -170,55 +151,46 @@ function serviceHost(serviceName)
151 case '-d':
152 if (!this._svcManager) { this._svcManager = new serviceManager(); }
153 this._svcManager.getService(this._ServiceOptions.name).start();
173 - console.log(this._ServiceOptions.name + ' starting...');
154 + console.log(this._ServiceOptions.name + ' starting.');
155 process.exit();
156 break;
157 case 'stop':
158 case '-s':
159 if (!this._svcManager) { this._svcManager = new serviceManager(); }
160 this._svcManager.getService(this._ServiceOptions.name).stop();
180 - console.log(this._ServiceOptions.name + ' stopping...');
161 + console.log(this._ServiceOptions.name + ' stopping.');
162 process.exit();
163 break;
164
165 }
166 }
167
187 - if (process.platform == 'win32')
188 - {
168 + if (process.platform == 'win32') {
169 var serviceTable = this.GM.CreateVariable(4 * this.GM.PointerSize);
170 this._ServiceName.pointerBuffer().copy(serviceTable.toBuffer());
171 this._ServiceMain.pointerBuffer().copy(serviceTable.toBuffer(), this.GM.PointerSize);
172 this._sscd = this.Advapi.StartServiceCtrlDispatcherA(serviceTable);
173 this._sscd.parent = this;
174 this._sscd.on('done', function OnStartServiceCtrlDispatcherA(retVal) {
195 - if (retVal.Val == 0)
196 - {
197 - this.parent.emit('normalStart');
198 - }
175 + if (retVal.Val == 0) { this.parent.emit('normalStart'); }
176 });
177 return;
178 }
202 -
179 +
180 var moduleName = this._ServiceOptions ? this._ServiceOptions.name : process.execPath.substring(1 + process.execPath.lastIndexOf('/'));
181
205 - for (var i = 0; i < process.argv.length; ++i)
206 - {
207 - switch(process.argv[i])
208 - {
182 + for (var i = 0; i < process.argv.length; ++i) {
183 + switch (process.argv[i].toLowerCase()) {
184 case 'start':
185 case '-d':
186 var child = require('child_process').execFile(process.execPath, [moduleName], { type: require('child_process').SpawnTypes.DETACHED });
187 var pstream = null;
213 - try
214 - {
188 + try {
189 pstream = require('fs').createWriteStream('/var/run/' + moduleName + '.pid', { flags: 'w' });
190 }
217 - catch(e)
218 - {
191 + catch (e) {
192 }
220 - if (pstream == null)
221 - {
193 + if (pstream == null) {
194 pstream = require('fs').createWriteStream('.' + moduleName + '.pid', { flags: 'w' });
195 }
196 pstream.end(child.pid.toString());
@@ -229,33 +201,26 @@ function serviceHost(serviceName)
201 case 'stop':
202 case '-s':
203 var pid = null;
232 - try
233 - {
204 + try {
205 pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
206 require('fs').unlinkSync('/var/run/' + moduleName + '.pid');
207 }
237 - catch(e)
238 - {
208 + catch (e) {
209 }
240 - if(pid == null)
241 - {
242 - try
243 - {
210 + if (pid == null) {
211 + try {
212 pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
213 require('fs').unlinkSync('.' + moduleName + '.pid');
214 }
247 - catch(e)
248 - {
215 + catch (e) {
216 }
217 }
218
252 - if(pid)
253 - {
219 + if (pid) {
220 process.kill(pid);
221 console.log(moduleName + ' stopped');
222 }
257 - else
258 - {
223 + else {
224 console.log(moduleName + ' not running');
225 }
226 process.exit();
@@ -263,56 +228,30 @@ function serviceHost(serviceName)
228 }
229 }
230
266 - if(serviceOperation == 0)
267 - {
231 + if (serviceOperation == 0) {
232 // This is non-windows, so we need to check how this binary was started to determine if this was a service start
233
234 // Start by checking if we were started with start/stop
235 var pid = null;
272 - try
273 - {
274 - pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
275 - }
276 - catch (e)
277 - {
278 - }
279 - if (pid == null)
280 - {
281 - try
282 - {
283 - pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
284 - }
285 - catch (e)
286 - {
287 - }
288 - }
289 -
290 - if (pid != null && pid == process.pid)
291 - {
236 + try { pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' })); } catch (e) { }
237 + if (pid == null) { try { pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' })); } catch (e) { } }
238 +
239 + if (pid != null && pid == process.pid) {
240 this.emit('serviceStart');
293 - }
294 - else
295 - {
241 + } else {
242 // Now we need to check if we were started with systemd
297 - if (require('processManager').getProcessInfo(1).Name == 'systemd')
298 - {
243 + if (require('processManager').getProcessInfo(1).Name == 'systemd') {
244 this._checkpid = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
245 this._checkpid.result = '';
246 this._checkpid.parent = this;
302 - this._checkpid.on('exit', function onCheckPIDExit()
303 - {
247 + this._checkpid.on('exit', function onCheckPIDExit() {
248 var lines = this.result.split('\r\n');
305 - for (i in lines)
306 - {
307 - if(lines[i].startsWith(' Main PID:'))
308 - {
249 + for (i in lines) {
250 + if (lines[i].startsWith(' Main PID:')) {
251 var tokens = lines[i].split(' ');
310 - if (parseInt(tokens[3]) == process.pid)
311 - {
252 + if (parseInt(tokens[3]) == process.pid) {
253 this.parent.emit('serviceStart');
313 - }
314 - else
315 - {
254 + } else {
255 this.parent.emit('normalStart');
256 }
257 delete this.parent._checkpid;
@@ -326,8 +265,7 @@ function serviceHost(serviceName)
265 this._checkpid.stdin.write("systemctl status " + moduleName + " | grep 'Main PID:'\n");
266 this._checkpid.stdin.write('exit\n');
267 }
329 - else
330 - {
268 + else {
269 // This isn't even a systemd platform, so this couldn't have been a service start
270 this.emit('normalStart');
271 }
agents/modules_meshcmd/serviceManager.js
+44 -91
@@ -1,7 +1,6 @@
1
2
3 -function parseServiceStatus(token)
4 -{
3 +function parseServiceStatus(token) {
4 var j = {};
5 var serviceType = token.Deref(0, 4).IntVal;
6 j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
@@ -9,8 +8,7 @@ function parseServiceStatus(token)
8 j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
9 j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
10 j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
12 - switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
13 - {
11 + switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE()) {
12 case 0x00000005:
13 j.state = 'CONTINUE_PENDING';
14 break;
@@ -35,8 +33,7 @@ function parseServiceStatus(token)
33 }
34 var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
35 j.controlsAccepted = [];
38 - if ((controlsAccepted & 0x00000010) == 0x00000010)
39 - {
36 + if ((controlsAccepted & 0x00000010) == 0x00000010) {
37 j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
38 j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
39 j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
@@ -54,10 +51,8 @@ function parseServiceStatus(token)
51 return (j);
52 }
53
57 -function serviceManager()
58 -{
59 - if (process.platform == 'win32')
60 - {
54 +function serviceManager() {
55 + if (process.platform == 'win32') {
56 this.GM = require('_GenericMarshal');
57 this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
58 this.proxy.CreateMethod('OpenSCManagerA');
@@ -83,40 +78,31 @@ function serviceManager()
78 var AdministratorsGroup = this.GM.CreatePointer();
79 var admin = false;
80
86 - if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
87 - {
81 + if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0) {
82 var member = this.GM.CreateInteger();
89 - if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
90 - {
83 + if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0) {
84 if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
85 }
86 this.proxy.FreeSid(AdministratorsGroup.Deref());
87 }
88 return admin;
89 };
97 - this.getServiceFolder = function getServiceFolder()
98 - {
90 + this.getServiceFolder = function getServiceFolder() {
91 var destinationFolder = null;
100 - if (require('os').arch() == 'x64')
101 - {
92 + if (require('os').arch() == 'x64') {
93 // 64 bit Windows
103 - if (this.GM.PointerSize == 4)
104 - {
94 + if (this.GM.PointerSize == 4) {
95 // 32 Bit App
96 destinationFolder = process.env['ProgramFiles(x86)'];
107 - }
108 - else
109 - {
97 + } else {
98 // 64 bit App
99 destinationFolder = process.env['ProgramFiles'];
100 }
113 - }
114 - else
115 - {
101 + } else {
102 // 32 bit Windows
103 destinationFolder = process.env['ProgramFiles'];
104 }
119 - return (destinationFolder + '\\mesh');
105 + return (destinationFolder + '\\Open Source\\MeshCmd');
106 };
107
108 this.enumerateService = function () {
@@ -129,9 +115,7 @@ function serviceManager()
115 var resumeHandle = this.GM.CreatePointer();
116 //var services = this.proxy.CreateVariable(262144);
117 var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
132 - if (bytesNeeded.IntVal <= 0) {
133 - throw ('error enumerating services');
134 - }
118 + if (bytesNeeded.IntVal <= 0) { throw('Error enumerating services'); }
119 var sz = bytesNeeded.IntVal;
120 var services = this.GM.CreateVariable(sz);
121 this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
@@ -157,7 +141,7 @@ function serviceManager()
141 var ptr = this.GM.CreatePointer();
142 var bytesNeeded = this.GM.CreateVariable(ptr._size);
143 var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
160 - if (handle.Val == 0) { throw ('could not open ServiceManager'); }
144 + if (handle.Val == 0) { throw('Could not open ServiceManager'); }
145 var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
146 if (h.Val != 0) {
147 var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
@@ -182,51 +166,46 @@ function serviceManager()
166 }
167 }
168 else {
185 - throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
169 + throw ('Cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
170 }
171 }
172 retVal.start = function () {
173 if (this.status.state == 'STOPPED') {
174 var success = this._proxy.StartServiceA(this._service, 0, 0);
191 - if (success == 0) {
192 - throw (this.name + '.start() failed');
193 - }
194 - }
195 - else {
196 - throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
175 + if (success == 0) { throw (this.name + '.start() failed'); }
176 + } else {
177 + throw ('Cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
178 }
179 }
180 return (retVal);
200 - }
201 - else {
181 + } else {
182
183 }
184 }
185
186 this.proxy.CloseServiceHandle(handle);
207 - throw ('could not find service: ' + name);
187 + throw ('Could not find service: ' + name);
188 }
189 }
210 - this.installService = function installService(options)
211 - {
212 - if (process.platform == 'win32')
213 - {
214 - if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
190 + this.installService = function installService(options) {
191 + if (process.platform == 'win32') {
192 + if (!this.isAdmin()) { throw ('Installing as Service, requires administrator permissions.'); }
193
194 // Before we start, we need to copy the binary to the right place
195 var folder = this.getServiceFolder();
196 if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
197 require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
198 options.servicePath = folder + '\\' + options.name + '.exe';
199 + console.log('Installing to "' + options.servicePath + '"');
200
201 var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
202 var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
224 - if (handle.Val == 0) { throw ('error opening SCManager'); }
203 + if (handle.Val == 0) { throw ('Error opening SCManager'); }
204 var serviceName = this.GM.CreateVariable(options.name);
205 var displayName = this.GM.CreateVariable(options.name);
206 var allAccess = 0x000F01FF;
207 var serviceType;
229 -
208 +
209
210 switch (options.startType) {
211 case 'BOOT_START':
@@ -264,13 +243,11 @@ function serviceManager()
243 this.proxy.CloseServiceHandle(handle);
244 return (this.getService(options.name));
245 }
267 - if(process.platform == 'linux')
268 - {
269 - switch (this.getServiceType())
270 - {
246 + if (process.platform == 'linux') {
247 + switch (this.getServiceType()) {
248 case 'init':
249 require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
273 - console.log('copying ' + options.servicePath);
250 + console.log('Copying ' + options.servicePath);
251 var m = require('fs').statSync('/etc/init.d/' + options.name).mode;
252 m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
253 require('fs').chmodSync('/etc/init.d/' + options.name, m);
@@ -305,40 +282,25 @@ function serviceManager()
282 }
283 }
284 }
308 - this.uninstallService = function uninstallService(name)
309 - {
285 + this.uninstallService = function uninstallService(name) {
286 if (typeof (name) == 'object') { name = name.name; }
311 - if (process.platform == 'win32')
312 - {
313 - if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
287 + if (process.platform == 'win32') {
288 + if (!this.isAdmin()) { throw ('Uninstalling a service, requires administrator permissions.'); }
289
290 var service = this.getService(name);
316 - if (service.status.state == undefined || service.status.state == 'STOPPED')
317 - {
318 - if (this.proxy.DeleteService(service._service) == 0)
319 - {
291 + if (service.status.state == undefined || service.status.state == 'STOPPED') {
292 + if (this.proxy.DeleteService(service._service) == 0) {
293 throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
321 - }
322 - else
323 - {
324 - try
325 - {
326 - require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
327 - }
328 - catch(e)
329 - {
330 - }
294 + } else {
295 + try { require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe'); } catch (e) { }
296 }
297 }
333 - else
334 - {
298 + else {
299 throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
300 }
301 }
338 - else if(process.platform == 'linux')
339 - {
340 - switch (this.getServiceType())
341 - {
302 + else if (process.platform == 'linux') {
303 + switch (this.getServiceType()) {
304 case 'init':
305 this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
306 this._update._svcname = name;
@@ -346,11 +308,7 @@ function serviceManager()
308 try {
309 require('fs').unlinkSync('/etc/init.d/' + this._svcname);
310 console.log(this._svcname + ' uninstalled');
349 -
350 - }
351 - catch (e) {
352 - console.log(this._svcname + ' could not be uninstalled')
353 - }
311 + } catch (e) { console.log(this._svcname + ' could not be uninstalled'); }
312 process.exit();
313 });
314 this._update.stdout.on('data', function (chunk) { });
@@ -366,10 +324,7 @@ function serviceManager()
324 require('fs').unlinkSync('/usr/local/mesh/' + this._svcname);
325 require('fs').unlinkSync('/lib/systemd/system/' + this._svcname + '.service');
326 console.log(this._svcname + ' uninstalled');
369 - }
370 - catch (e) {
371 - console.log(this._svcname + ' could not be uninstalled')
372 - }
327 + } catch (e) { console.log(this._svcname + ' could not be uninstalled'); }
328 process.exit();
329 });
330 this._update.stdout.on('data', function (chunk) { });
@@ -382,10 +337,8 @@ function serviceManager()
337 }
338 }
339 }
385 - if(process.platform == 'linux')
386 - {
387 - this.getServiceType = function getServiceType()
388 - {
340 + if (process.platform == 'linux') {
341 + this.getServiceType = function getServiceType() {
342 return (require('processManager').getProcessInfo(1).Name);
343 };
344 }
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.1.5-u",
3 + "version": "0.1.5-v",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",