Added RunCommand to MeshCtrl.js
Ylian Saint-Hilaire committed
Jul 13, 2020 at 12:25 UTC
0c3157f3a20f01ac5e6f9b7dfed0b82d22497301
2 files changed
+56
-3
meshctrl.js
+24
-1
@@ -7,7 +7,7 @@ try { require('ws'); } catch (ex) { console.log('Missing module "ws", type "npm
7
var settings = {};
8
const crypto = require('crypto');
9
const args = require('minimist')(process.argv.slice(2));
10
-const possibleCommands = ['listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'addusergroup', 'listusergroups', 'removeusergroup'];
10
+const possibleCommands = ['listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand'];
11
if (args.proxy != null) { try { require('https-proxy-agent'); } catch (ex) { console.log('Missing module "https-proxy-agent", type "npm install https-proxy-agent" to install it.'); return; } }
12
13
if (args['_'].length == 0) {
@@ -41,6 +41,7 @@ if (args['_'].length == 0) {
41
console.log(" GenerateInviteLink - Create an invitation link.");
42
console.log(" Broadcast - Display a message to all online users.");
43
console.log(" ShowEvents - Display real-time server events in JSON format.");
44
+ console.log(" RunCommand - Run a shell command on a remote device.");
45
console.log("\r\nSupported login arguments:");
46
console.log(" --url [wss://server] - Server url, wss://localhost:443 is default.");
47
console.log(" --loginuser [username] - Login username, admin is default.");
@@ -158,6 +159,12 @@ if (args['_'].length == 0) {
159
else { ok = true; }
160
break;
161
}
162
+ case 'runcommand': {
163
+ if (args.id == null) { console.log("Missing device id, use --id [deviceid]"); }
164
+ else if (args.run == null) { console.log("Missing run, use --run \"command\""); }
165
+ else { ok = true; }
166
+ break;
167
+ }
168
case 'help': {
169
if (args['_'].length < 2) {
170
console.log("Get help on an action. Type:\r\n\r\n help [action]\r\n\r\nPossible actions are: " + possibleCommands.join(', ') + '.');
@@ -410,6 +417,17 @@ if (args['_'].length == 0) {
417
console.log(" --json - Give results in JSON format.");
418
break;
419
}
420
+ case 'runcommand': {
421
+ console.log("Run a shell command on a remote device, Example usages:\r\n");
422
+ console.log(" MeshCtrl RunCommand --id deviceid --run \"command\"");
423
+ console.log(" MeshCtrl RunCommand --id deviceid --run \"command\" --powershell");
424
+ console.log("\r\nRequired arguments:\r\n");
425
+ console.log(" --id [deviceid] - The device identifier.");
426
+ console.log(" --run \"[command]\" - Shell command to execute on the remote device.");
427
+ console.log("\r\nOptional arguments:\r\n");
428
+ console.log(" --powershell - Run in Windows PowerShell.");
429
+ break;
430
+ }
431
default: {
432
console.log("Get help on an action. Type:\r\n\r\n help [action]\r\n\r\nPossible actions are: " + possibleCommands.join(', ') + '.');
433
}
@@ -768,6 +786,10 @@ function serverConnect() {
786
ws.send(JSON.stringify({ action: 'getsysinfo', nodeid: args.id, nodeinfo: true, responseid: 'meshctrl' }));
787
break;
788
}
789
+ case 'runcommand': {
790
+ ws.send(JSON.stringify({ action: 'runcommands', nodeids: [args.id], type: ((args.powershell) ? 2 : 0), cmds: args.run, responseid: 'meshctrl' }));
791
+ break;
792
+ }
793
}
794
});
795
@@ -847,6 +869,7 @@ function serverConnect() {
869
case 'adddeviceuser': //
870
case 'createusergroup': //
871
case 'deleteusergroup': //
872
+ case 'runcommands':
873
case 'userbroadcast': { // BROADCAST
874
if (data.responseid == 'meshctrl') {
875
if (data.meshid) { console.log(data.result, data.meshid); }
meshuser.js
+32
-2
@@ -3370,10 +3370,32 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3370
if (typeof command.cmds != 'string') break; // Check commands
3371
3372
for (i in command.nodeids) {
3373
+ var nodeid = command.nodeids[i], err = null;
3374
+
3375
+ // Argument validation
3376
+ if (common.validateString(nodeid, 1, 1024) == false) { err = 'Invalid nodeid'; } // Check nodeid
3377
+ else {
3378
+ if (nodeid.indexOf('/') == -1) { nodeid = 'node/' + domain.id + '/' + nodeid; }
3379
+ if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
3380
+ }
3381
+ if (err != null) {
3382
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: err })); } catch (ex) { } }
3383
+ continue;
3384
+ }
3385
+
3386
// Get the node and the rights for this node
3374
- parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
3387
+ parent.GetNodeWithRights(domain, user, nodeid, function (node, rights, visible) {
3388
+ // Check if this node was found
3389
+ if (node == null) {
3390
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Invalid nodeid' })); } catch (ex) { } }
3391
+ return;
3392
+ }
3393
+
3394
// Check we have the rights to run commands on this device
3376
- if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
3395
+ if ((rights & MESHRIGHT_REMOTECONTROL) == 0) {
3396
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Access denied' })); } catch (ex) { } }
3397
+ return;
3398
+ }
3399
3400
// Get the agent and run the commands
3401
var agent = parent.wsagents[node._id];
@@ -3384,13 +3406,21 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3406
if ((agent.agentInfo.agentId > 0) && (agent.agentInfo.agentId < 5)) {
3407
// Windows Agent
3408
if ((command.type == 1) || (command.type == 2)) { commandsOk = true; }
3409
+ else if (command.type === 0) { command.type = 1; commandsOk = true; } // Set the default type of this agent
3410
} else {
3411
// Non-Windows Agent
3412
if (command.type == 3) { commandsOk = true; }
3413
+ else if (command.type === 0) { command.type = 3; commandsOk = true; } // Set the default type of this agent
3414
}
3415
if (commandsOk == true) {
3416
+ // Send the commands to the agent
3417
try { agent.send(JSON.stringify({ action: 'runcommands', type: command.type, cmds: command.cmds })); } catch (ex) { }
3418
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'OK' })); } catch (ex) { } }
3419
+ } else {
3420
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Invalid command type' })); } catch (ex) { } }
3421
}
3422
+ } else {
3423
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Agent not connected' })); } catch (ex) { } }
3424
}
3425
});
3426
}