diff --git a/meshuser.js b/meshuser.js index 96db7aad..9373582a 100644 --- a/meshuser.js +++ b/meshuser.js @@ -2784,92 +2784,111 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use { 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 if (typeof command.runAsUser != 'number') { command.runAsUser = 0; } // Check runAsUser - for (i in command.nodeids) { - var nodeid = command.nodeids[i], err = null; + const processRunCommand = function (command) { + for (i in command.nodeids) { + var nodeid = command.nodeids[i], err = null; - // Argument validation - if (common.validateString(nodeid, 1, 1024) == false) { err = 'Invalid nodeid'; } // Check nodeid - else { - if (nodeid.indexOf('/') == -1) { nodeid = 'node/' + domain.id + '/' + nodeid; } - if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain - } - if (err != null) { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: err })); } catch (ex) { } } - continue; - } - - // Get the node and the rights for this node - parent.GetNodeWithRights(domain, user, nodeid, function (node, rights, visible) { - // Check if this node was found - if (node == null) { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Invalid nodeid' })); } catch (ex) { } } - return; + // Argument validation + if (common.validateString(nodeid, 1, 1024) == false) { err = 'Invalid nodeid'; } // Check nodeid + else { + if (nodeid.indexOf('/') == -1) { nodeid = 'node/' + domain.id + '/' + nodeid; } + if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain + } + if (err != null) { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: err })); } catch (ex) { } } + continue; } - if (command.type == 4) { - // This is an agent console command - - // Check we have the rights to run commands on this device, MESHRIGHT_REMOTECONTROL & MESHRIGHT_AGENTCONSOLE are needed - if ((rights & 24) != 24) { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Access denied' })); } catch (ex) { } } + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, nodeid, function (node, rights, visible) { + // Check if this node was found + if (node == null) { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Invalid nodeid' })); } catch (ex) { } } return; } - // Send the commands to the agent - var agent = parent.wsagents[node._id]; - if ((agent != null) && (agent.authenticated == 2) && (agent.agentInfo != null)) { - try { agent.send(JSON.stringify({ action: 'msg', type: 'console', value: command.cmds, rights: rights, sessionid: ws.sessionId })); } catch (ex) { } - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'OK' })); } catch (ex) { } } - } else { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Agent not connected' })); } catch (ex) { } } - } - } else { - // This is a standard (bash/shell/powershell) command. + if (command.type == 4) { + // This is an agent console command - // Check we have the rights to run commands on this device - if ((rights & MESHRIGHT_REMOTECOMMAND) == 0) { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Access denied' })); } catch (ex) { } } - 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 if (command.type === 0) { command.type = 1; commandsOk = true; } // Set the default type of this agent - } else { - // Non-Windows Agent - if (command.type == 3) { commandsOk = true; } - else if (command.type === 0) { command.type = 3; commandsOk = true; } // Set the default type of this agent + // Check we have the rights to run commands on this device, MESHRIGHT_REMOTECONTROL & MESHRIGHT_AGENTCONSOLE are needed + if ((rights & 24) != 24) { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Access denied' })); } catch (ex) { } } + return; } - if (commandsOk == true) { - // Send the commands to the agent - try { agent.send(JSON.stringify({ action: 'runcommands', type: command.type, cmds: command.cmds, runAsUser: command.runAsUser })); } catch (ex) { } + + // Send the commands to the agent + var agent = parent.wsagents[node._id]; + if ((agent != null) && (agent.authenticated == 2) && (agent.agentInfo != null)) { + try { agent.send(JSON.stringify({ action: 'msg', type: 'console', value: command.cmds, rights: rights, sessionid: ws.sessionId })); } catch (ex) { } if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'OK' })); } catch (ex) { } } - - // Send out an event that these commands where run on this device - var targets = parent.CreateNodeDispatchTargets(node.meshid, node._id, ['server-users', user._id]); - var msgid = 24; // "Running commands" - if (command.type == 1) { msgid = 99; } // "Running commands as user" - if (command.type == 2) { msgid = 100; } // "Running commands as user if possible" - var event = { etype: 'node', userid: user._id, username: user.name, nodeid: node._id, action: 'runcommands', msg: 'Running commands', msgid: msgid, cmds: command.cmds, cmdType: command.type, runAsUser: command.runAsUser, domain: domain.id }; - parent.parent.DispatchEvent(targets, obj, event); } else { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Invalid command type' })); } catch (ex) { } } + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Agent not connected' })); } catch (ex) { } } } } else { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Agent not connected' })); } catch (ex) { } } + // This is a standard (bash/shell/powershell) command. + + // Check we have the rights to run commands on this device + if ((rights & MESHRIGHT_REMOTECOMMAND) == 0) { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Access denied' })); } catch (ex) { } } + 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 if (command.type === 0) { command.type = 1; commandsOk = true; } // Set the default type of this agent + } else { + // Non-Windows Agent + if (command.type == 3) { commandsOk = true; } + else if (command.type === 0) { command.type = 3; commandsOk = true; } // Set the default type of this agent + } + if (commandsOk == true) { + // Send the commands to the agent + try { agent.send(JSON.stringify({ action: 'runcommands', type: command.type, cmds: command.cmds, runAsUser: command.runAsUser })); } catch (ex) { } + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'OK' })); } catch (ex) { } } + + // Send out an event that these commands where run on this device + var targets = parent.CreateNodeDispatchTargets(node.meshid, node._id, ['server-users', user._id]); + var msgid = 24; // "Running commands" + if (command.type == 1) { msgid = 99; } // "Running commands as user" + if (command.type == 2) { msgid = 100; } // "Running commands as user if possible" + var event = { etype: 'node', userid: user._id, username: user.name, nodeid: node._id, action: 'runcommands', msg: 'Running commands', msgid: msgid, cmds: command.cmds, cmdType: command.type, runAsUser: command.runAsUser, domain: domain.id }; + parent.parent.DispatchEvent(targets, obj, event); + } else { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Invalid command type' })); } catch (ex) { } } + } + } else { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'runcommands', responseid: command.responseid, result: 'Agent not connected' })); } catch (ex) { } } + } } - } - }); + }); + } + } + + if (typeof command.cmdpath == 'string') { + // If a server command path is used, load the script from the path + var file = parent.getServerFilePath(user, domain, command.cmdpath); + if (file != null) { + fs.readFile(file.fullpath, function (err, data) { + // If loaded correctly, run loaded commands + if ((err != null) || (data == null) || (data.length == 0) || (data.length > 65535)) return; + command.cmds = data.toString(); + delete command.cmdpath; + processRunCommand(command); + }); + } + } else if (typeof command.cmds == 'string') { + // Run provided commands + if (command.cmds.length > 65535) return; + processRunCommand(command); } break; } diff --git a/public/styles/style.css b/public/styles/style.css index 9edfe95a..0493c4d5 100644 --- a/public/styles/style.css +++ b/public/styles/style.css @@ -591,14 +591,14 @@ body { width: 260px; } -#d3serveraction { +#d3serveraction, #d2serveraction { width: 100%; background-color: #d3d9d6; text-align: left; padding: 3px; } -#d3serverfiles { +#d3serverfiles, #d2serverfiles { width: 100%; height: 150px; background-color: white; diff --git a/views/default.handlebars b/views/default.handlebars index 21b35959..69c87754 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1281,7 +1281,7 @@
-   +  
@@ -5731,15 +5731,17 @@ x += ''; x += ''; x += ''; x += ''; - x += ''; + if (userinfo.siteadmin & 8) { x += ''; } setDialogMode(2, "Run Commands", 3, d2groupActionFunctionRunCommands, x, options); Q('d2runcmd').focus(); d2runCommandValidate(); + if (userinfo.siteadmin & 8) { d3fileoptions = { dialog: 2, files: 'd2serverfiles', folderup: 'p2FolderUp', currentFolder: 'p2CurrentFolder', func: null }; d3updatefiles(); } // Update the server files } } + function d2runCommandValidate() { QV('d2cmduser', Q('d2cmdtype').value < 4); QV('d2runcmd', Q('d2cmdsource').value == 0); @@ -5751,6 +5753,7 @@ if (Q('d2cmdsource').value == 2) { ok = false; } // From server file QE('idx_dlgOkButton', ok); } + function d2groupActionFunctionRunCommands(b, options) { var type = 3; try { type = parseInt(Q('d2cmdtype').value); } catch (ex) { } @@ -5770,7 +5773,11 @@ } if (Q('d2cmdsource').value == 2) { // From server file - cmd.cmds = ''; + var files = d3getFileSel(); + if (files.length != 1) return; + cmd.cmdpath = d3filetreelocation.join('/') + '/' + files[0]; + meshserver.send(cmd); + if (options.func) { options.func(); } } } @@ -16115,6 +16122,7 @@ // function d3init() { + d3fileoptions = { dialog: 1, filter: 'd3filter', files: 'd3serverfiles', folderup: 'p3FolderUp', currentFolder: 'p3CurrentFolder', func: d3setActions }; Q('d3localFile').value = ''; Q('d3localFile').accept = Q('d3filter').value; d3modechange(); @@ -16129,10 +16137,11 @@ var d3filetreelinkpath; var d3filetreelocation = []; - + var d3fileoptions = null; function d3updatefiles() { - if (Q('d3uploadMode').value == 1) return; - var html1 = '', html2 = '', filetreex = filetree, folderdepth = 1, publicPath = null; + if (d3fileoptions == null) return; + if ((d3fileoptions.filter == 'd3filter') && (Q('d3uploadMode').value == 1)) return; + var html1 = '', html2 = '', filetreex = filetree, folderdepth = 1, publicPath = null, lastFolderName = ''; // Navigate to path location, build the paths at the same time var d3filetreelocation2 = [], oldlinkpath = d3filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc'); @@ -16150,6 +16159,7 @@ if (d3filetreelinkpath != '') { d3filetreelinkpath += '/' + d3filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + d3filetreelocation[i]; } } } filetreex = filetreex.f[d3filetreelocation[i]]; + lastFolderName = filetreex.n; folderdepth++; } else { break; @@ -16161,7 +16171,8 @@ var filetreexx = p5sort_files(filetreex.f); // File filter - var fileFilter = Q('d3filter').value + var fileFilter = ''; + if (d3fileoptions.filter) { fileFilter = Q(d3fileoptions.filter).value }; // Display all files and folders at this location for (var i in filetreexx) { @@ -16189,19 +16200,24 @@ if (f.t < 3) { html1 += h; } else { html2 += h; } } - QH('d3serverfiles', html1 + html2); - QE('p3FolderUp', d3filetreelocation.length > 0); - d3setActions(); + if (d3fileoptions.currentFolder) { QH(d3fileoptions.currentFolder, lastFolderName); } + QH(d3fileoptions.files, html1 + html2); + QE(d3fileoptions.folderup, d3filetreelocation.length > 0); + if (d3fileoptions.func) { d3fileoptions.func(); } } function d3folderset(x) { d3filetreelocation.push(decodeURIComponent(x)); d3updatefiles(); return false; } function d3folderup(x) { if (x == null) { d3filetreelocation.pop(); } else { while (d3filetreelocation.length > x) { d3filetreelocation.pop(); } } d3updatefiles(); } function d3getFileSel() { var cc = []; var checkboxes = document.getElementsByName('fcx'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { cc.push(checkboxes[i].value) } } return cc; } function d3setActions() { - var mode = Q('d3uploadMode').value; - if (mode == 1) { - QE('idx_dlgOkButton', Q('d3localFile').value.length > 0); - } else { + if (d3fileoptions.dialog == 1) { + var mode = Q('d3uploadMode').value; + if (mode == 1) { + QE('idx_dlgOkButton', Q('d3localFile').value.length > 0); + } else { + QE('idx_dlgOkButton', d3getFileSel().length == 1); + } + } else if (d3fileoptions.dialog == 2) { QE('idx_dlgOkButton', d3getFileSel().length == 1); } }