mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 22:25:52 -05:00
Added batch command execution.
This commit is contained in:
parent
99345f7259
commit
cf8f58cd48
@ -891,6 +891,39 @@ function createMeshCore(agent) {
|
||||
for (var i in data.macs) { sendWakeOnLan(data.macs[i]); }
|
||||
break;
|
||||
}
|
||||
case 'runcommands': {
|
||||
if (mesh.cmdchild != null) { sendConsoleText("Run commands can't execute, already busy."); break; }
|
||||
MeshServerLog("Running commands", data);
|
||||
sendConsoleText("Run commands: " + data.cmds);
|
||||
if (process.platform == 'win32') {
|
||||
if (data.type == 1) {
|
||||
// Windows command shell
|
||||
mesh.cmdchild = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
|
||||
mesh.cmdchild.descriptorMetadata = 'UserCommandsShell';
|
||||
mesh.cmdchild.stdout.on('data', function (c) { sendConsoleText(c.toString()); });
|
||||
mesh.cmdchild.stderr.on('data', function (c) { sendConsoleText(c.toString()); });
|
||||
mesh.cmdchild.stdin.write(data.cmds + '\r\nexit\r\n');
|
||||
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
|
||||
} else if (data.type == 2) {
|
||||
// Windows Powershell
|
||||
mesh.cmdchild = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-']);
|
||||
mesh.cmdchild.descriptorMetadata = 'UserCommandsPowerShell';
|
||||
mesh.cmdchild.stdout.on('data', function (c) { sendConsoleText(c.toString()); });
|
||||
mesh.cmdchild.stderr.on('data', function (c) { sendConsoleText(c.toString()); });
|
||||
mesh.cmdchild.stdin.write(data.cmds + '\r\nexit\r\n');
|
||||
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
|
||||
}
|
||||
} else if (data.type == 3) {
|
||||
// Linux shell
|
||||
mesh.cmdchild = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
mesh.cmdchild.descriptorMetadata = 'UserCommandsShell';
|
||||
mesh.cmdchild.stdout.on('data', function (c) { sendConsoleText(c.toString()); });
|
||||
mesh.cmdchild.stderr.on('data', function (c) { sendConsoleText(c.toString()); });
|
||||
mesh.cmdchild.stdin.write(data.cmds.split('\r').join('') + '\nexit\n');
|
||||
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
// Uninstall this agent
|
||||
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
|
||||
|
41
meshuser.js
41
meshuser.js
@ -3338,18 +3338,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
db.Get('if' + node._id, function (err, nodeifs) {
|
||||
if ((nodeifs != null) && (nodeifs.length == 1)) {
|
||||
var macs = [], nodeif = nodeifs[0];
|
||||
for (var i in nodeif.netif) { if (nodeif.netif[i].mac) { macs.push(nodeif.netif[i].mac); } }
|
||||
for (var j in nodeif.netif) { if (nodeif.netif[j].mac) { macs.push(nodeif.netif[j].mac); } }
|
||||
|
||||
// Have the server send a wake-on-lan packet (Will not work in WAN-only)
|
||||
if (parent.parent.meshScanner != null) { parent.parent.meshScanner.wakeOnLan(macs); }
|
||||
|
||||
// Get the list of mesh this user as access to
|
||||
var targetMeshes = [];
|
||||
for (i in user.links) { targetMeshes.push(i); } // TODO: Include used security groups!!
|
||||
for (j in user.links) { targetMeshes.push(j); } // TODO: Include used security groups!!
|
||||
|
||||
// Go thru all the connected agents and send wake-on-lan on all the ones in the target mesh list
|
||||
for (i in parent.wsagents) {
|
||||
var agent = parent.wsagents[i];
|
||||
for (j in parent.wsagents) {
|
||||
var agent = parent.wsagents[j];
|
||||
if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) {
|
||||
//console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(','));
|
||||
try { agent.send(JSON.stringify({ action: 'wakeonlan', macs: macs })); } catch (ex) { }
|
||||
@ -3363,6 +3363,39 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'runcommands':
|
||||
{
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
if (typeof command.type != 'number') break; // Check command type
|
||||
if (typeof command.cmds != 'string') break; // Check commands
|
||||
|
||||
for (i in command.nodeids) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check we have the rights to run commands on this device
|
||||
if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
|
||||
|
||||
// Get the agent and run the commands
|
||||
var agent = parent.wsagents[node._id];
|
||||
if ((agent != null) && (agent.authenticated == 2) && (agent.agentInfo != null)) {
|
||||
// Check if this agent is correct for this command type
|
||||
// command.type 1 = Windows Command, 2 = Windows PowerShell, 3 = Linux/BSD/macOS
|
||||
var commandsOk = false;
|
||||
if ((agent.agentInfo.agentId > 0) && (agent.agentInfo.agentId < 5)) {
|
||||
// Windows Agent
|
||||
if ((command.type == 1) || (command.type == 2)) { commandsOk = true; }
|
||||
} else {
|
||||
// Non-Windows Agent
|
||||
if (command.type == 3) { commandsOk = true; }
|
||||
}
|
||||
if (commandsOk == true) {
|
||||
try { agent.send(JSON.stringify({ action: 'runcommands', type: command.type, cmds: command.cmds })); } catch (ex) { }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
{
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
|
20
package.json
20
package.json
@ -30,6 +30,8 @@
|
||||
"sample-config-advanced.json"
|
||||
],
|
||||
"dependencies": {
|
||||
"archiver": "^4.0.1",
|
||||
"archiver-zip-encrypted": "^1.0.8",
|
||||
"body-parser": "^1.19.0",
|
||||
"cbor": "^4.1.5",
|
||||
"compression": "^1.7.4",
|
||||
@ -39,16 +41,32 @@
|
||||
"express-handlebars": "^3.1.0",
|
||||
"express-ws": "^4.0.0",
|
||||
"html-minifier": "^4.0.0",
|
||||
"image-size": "^0.8.3",
|
||||
"ipcheck": "^0.1.0",
|
||||
"jsdom": "^16.3.0",
|
||||
"jwt-simple": "^0.5.6",
|
||||
"minify-js": "0.0.4",
|
||||
"minimist": "^1.2.0",
|
||||
"mongodb": "^3.5.9",
|
||||
"multiparty": "^4.2.1",
|
||||
"nedb": "^1.8.0",
|
||||
"node-forge": "^0.8.4",
|
||||
"node-rdpjs-2": "^0.3.5",
|
||||
"node-windows": "^1.0.0-beta.1",
|
||||
"otplib": "^10.2.3",
|
||||
"passport": "^0.4.1",
|
||||
"passport-azure-oauth2": "^0.1.0",
|
||||
"passport-github2": "^0.1.12",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-reddit": "^0.2.4",
|
||||
"passport-twitter": "^1.0.4",
|
||||
"promise": "^8.1.0",
|
||||
"saslprep": "^1.0.3",
|
||||
"twilio": "^3.48.0",
|
||||
"ws": "^6.2.1",
|
||||
"xmldom": "^0.1.27",
|
||||
"yauzl": "^2.10.0"
|
||||
"yauzl": "^2.10.0",
|
||||
"yubikeyotp": "^0.2.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"repository": {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4233,7 +4233,7 @@
|
||||
}
|
||||
|
||||
var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '<br /><br />';
|
||||
x += addHtmlValue("Operation", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Reset devices" + '</option><option value=2>' + "Power off devices" + '</option><option value=105>' + "Export device information" + '</option><option value=102>' + "Move to device group" + '</option>' + addedOptions + '<option value=101>' + "Delete devices" + '</option></select>');
|
||||
x += addHtmlValue("Operation", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=106>' + "Run commands" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Reset devices" + '</option><option value=2>' + "Power off devices" + '</option><option value=105>' + "Export device information" + '</option><option value=102>' + "Move to device group" + '</option>' + addedOptions + '<option value=101>' + "Delete devices" + '</option></select>');
|
||||
setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x);
|
||||
}
|
||||
|
||||
@ -4273,6 +4273,26 @@
|
||||
} else if (op == 105) {
|
||||
// Export device information
|
||||
p2downloadDeviceInfo();
|
||||
} else if (op == 106) {
|
||||
// Run commands
|
||||
var wintype = false, linuxtype = false, chkNodeIds = getCheckedDevices();
|
||||
for (var i in chkNodeIds) {
|
||||
var n = getNodeFromId(chkNodeIds[i]);
|
||||
if (n.agent) { if ((n.agent.id > 0) && (n.agent.id < 5)) { wintype = true; } else { linuxtype = true; } }
|
||||
}
|
||||
if ((wintype == true) || (linuxtype == true)) {
|
||||
var x = "Run commands on selected devices." + '<br /><br />';
|
||||
if (wintype == true) {
|
||||
x += '<select id=d2cmdtype style=width:100%>';
|
||||
x += '<option value=1>' + "Windows Command Prompt" + '</option><option value=2>' + "Windows PowerShell" + '</option>';
|
||||
if (linuxtype == true) { x += '<option value=3>' + "Linux/BSD/macOS Command Shell" + '</option>'; }
|
||||
x += '</select>';
|
||||
}
|
||||
x += '<textarea id=d2runcmd style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea>';
|
||||
setDialogMode(2, "Run Commands", 3, d2groupActionFunctionRunCommands, x);
|
||||
Q('d2runcmd').focus();
|
||||
//QE('idx_dlgOkButton', true);
|
||||
}
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
|
||||
@ -4309,6 +4329,11 @@
|
||||
|
||||
function d2groupActionFunctionDelCheck() { QE('idx_dlgOkButton', Q('d2check').checked); }
|
||||
function d2groupActionFunctionDelExec() { meshserver.send({ action: 'removedevices', nodeids: getCheckedDevices() }); uncheckAllDevices(); }
|
||||
function d2groupActionFunctionRunCommands() {
|
||||
var type = 3;
|
||||
try { type = parseInt(Q('d2cmdtype').value); } catch (ex) { }
|
||||
meshserver.send({ action: 'runcommands', nodeids: getCheckedDevices(), type: type, cmds: Q('d2runcmd').value }); uncheckAllDevices();
|
||||
}
|
||||
|
||||
function onSortSelectChange(skipsave) {
|
||||
sort = document.getElementById('sortselect').selectedIndex;
|
||||
@ -5763,7 +5788,7 @@
|
||||
var x = "Select an operation to perform on this device." + '<br /><br />';
|
||||
var y = '<select id=d2deviceop style=float:right;width:250px>';
|
||||
if ((rights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((rights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((rights & 8) != 0) { y += '<option value=106>' + "Run Commands" + '</option><option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((rights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
y += '</select>';
|
||||
@ -5782,12 +5807,29 @@
|
||||
} else if (op == 104) {
|
||||
// Uninstall agent
|
||||
p10showSendUninstallAgentDialog([currentNode._id]);
|
||||
} else if (op == 106) {
|
||||
// Run commands
|
||||
var wintype = false, linuxtype = false;
|
||||
if (currentNode.agent) { if ((currentNode.agent.id > 0) && (currentNode.agent.id < 5)) { wintype = true; } else { linuxtype = true; } }
|
||||
if ((wintype == true) || (linuxtype == true)) {
|
||||
var x = "Run commands on this device." + '<br /><br />';
|
||||
if (wintype == true) { x += '<select id=d2cmdtype style=width:100%><option value=1>' + "Windows Command Prompt" + '</option><option value=2>' + "Windows PowerShell" + '</option></select>'; }
|
||||
x += '<textarea id=d2runcmd style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea>';
|
||||
setDialogMode(2, "Run Commands", 3, deviceRunCmdsFunctionEx, x);
|
||||
Q('d2runcmd').focus();
|
||||
}
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
|
||||
}
|
||||
}
|
||||
|
||||
function deviceRunCmdsFunctionEx() {
|
||||
var cmdType = 3;
|
||||
if ((currentNode.agent.id > 0) && (currentNode.agent.id < 5)) { cmdType = Q('d2cmdtype').value; }
|
||||
meshserver.send({ action: 'runcommands', nodeids: [ currentNode._id ], type: parseInt(cmdType), cmds: Q('d2runcmd').value });
|
||||
}
|
||||
|
||||
// Called when MeshCommander needs new credentials or updated credentials.
|
||||
function updateAmtCredentials(forceDialog) {
|
||||
var node = getNodeFromId(currentNode._id);
|
||||
@ -8043,7 +8085,6 @@
|
||||
if (mode == 3) { eventList = currentUserEvents; }
|
||||
for (var i in eventList) { if (eventList[i].h == h) { xevent = eventList[i]; break; } }
|
||||
if (xevent) {
|
||||
console.log(xevent);
|
||||
var x = '<div style=overflow-y:auto>';
|
||||
for (var i in xevent) {
|
||||
if ((i == 'h') || (i == '_id') || (i == 'ids') || (i == 'domain') || (xevent[i] == null) || (typeof xevent[i] == 'object')) continue;
|
||||
|
Loading…
Reference in New Issue
Block a user