diff --git a/agents/meshcore.js b/agents/meshcore.js index e18ce6eb..fb888f18 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1014,7 +1014,7 @@ function createMeshCore(agent) { } case 'wakeonlan': { // Send wake-on-lan on all interfaces for all MAC addresses in data.macs array. The array is a list of HEX MAC addresses. - sendConsoleText("Server requesting wake-on-lan for: " + data.macs.join(', ')); + //sendConsoleText("Server requesting wake-on-lan for: " + data.macs.join(', ')); for (var i in data.macs) { sendWakeOnLan(data.macs[i]); } break; } diff --git a/meshctrl.js b/meshctrl.js index 0f29f600..18888829 100644 --- a/meshctrl.js +++ b/meshctrl.js @@ -7,7 +7,7 @@ try { require('ws'); } catch (ex) { console.log('Missing module "ws", type "npm var settings = {}; const crypto = require('crypto'); const args = require('minimist')(process.argv.slice(2)); -const possibleCommands = ['edituser', 'listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download', 'deviceopenurl', 'devicemessage', 'devicetoast', 'addtousergroup', 'removefromusergroup', 'removeallusersfromusergroup', 'devicesharing']; +const possibleCommands = ['edituser', 'listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download', 'deviceopenurl', 'devicemessage', 'devicetoast', 'addtousergroup', 'removefromusergroup', 'removeallusersfromusergroup', 'devicesharing', 'devicepower']; 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; } } if (args['_'].length == 0) { @@ -53,6 +53,7 @@ if (args['_'].length == 0) { console.log(" DeviceOpenUrl - Open a URL on a remote device."); console.log(" DeviceMessage - Open a message box on a remote device."); console.log(" DeviceToast - Display a toast notification on a remote device."); + console.log(" DevicePower - Perform wake/sleep/reset/off operations on remote devices."); console.log(" DeviceSharing - View, add and remove sharing links for a given device."); console.log("\r\nSupported login arguments:"); console.log(" --url [wss://server] - Server url, wss://localhost:443 is default."); @@ -206,6 +207,11 @@ if (args['_'].length == 0) { else { ok = true; } break; } + case 'devicepower': { + if (args.id == null) { console.log(winRemoveSingleQuotes("Missing device id, use --id '[deviceid]'")); } + else { ok = true; } + break; + } case 'devicesharing': { if (args.id == null) { console.log(winRemoveSingleQuotes("Missing device id, use --id '[deviceid]'")); } else { ok = true; } @@ -715,6 +721,26 @@ if (args['_'].length == 0) { console.log(" --powershell - Run a Windows PowerShell."); break; } + case 'devicepower': { + console.log("Perform power operations on remote devices, Example usages:\r\n"); + console.log(winRemoveSingleQuotes(" MeshCtrl DevicePower --wake --id 'deviceid'")); + console.log(winRemoveSingleQuotes(" MeshCtrl DevicePower --sleep --id 'deviceid'")); + console.log(winRemoveSingleQuotes(" MeshCtrl DevicePower --reset --id 'deviceid'")); + console.log(winRemoveSingleQuotes(" MeshCtrl DevicePower --off --id 'deviceid1,deviceid2'")); + console.log("\r\nNote that some power operations may take up to a minute to execute.\r\n"); + console.log("Required arguments:\r\n"); + if (process.platform == 'win32') { + console.log(" --id [deviceid1,deviceid2] - Device identifiers."); + } else { + console.log(" --id '[deviceid1,deviceid2]' - Device identifiers."); + } + console.log("\r\nOptional arguments:\r\n"); + console.log(" --wake - Attempt to wake up the remote device."); + console.log(" --reset - Attempt to remote the remote device."); + console.log(" --sleep - Attempt to place the remote device in low power mode."); + console.log(" --off - Attempt to power off the remote device."); + break; + } case 'devicesharing': { var tzoffset = (new Date()).getTimezoneOffset() * 60000; // Offset in milliseconds var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5); @@ -722,7 +748,7 @@ if (args['_'].length == 0) { console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid'")); console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --remote abcdef")); console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --start " + localISOTime + " --duration 30")); - console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --type terminal --consent prompt")); + console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --type terminal --consent prompt")); console.log("\r\nRequired arguments:\r\n"); if (process.platform == 'win32') { console.log(" --id [deviceid] - The device identifier."); @@ -1317,6 +1343,26 @@ function serverConnect() { ws.send("{\"action\":\"authcookie\"}"); break; } + case 'devicepower': { + var nodes = args.id.split(','); + if (args.wake) { + // Wake operation + ws.send(JSON.stringify({ action: 'wakedevices', nodeids: nodes, responseid: 'meshctrl' })); + } else if (args.off) { + // Power off operation + ws.send(JSON.stringify({ action: 'poweraction', nodeids: nodes, actiontype: 2, responseid: 'meshctrl' })); + } else if (args.reset) { + // Reset operation + ws.send(JSON.stringify({ action: 'poweraction', nodeids: nodes, actiontype: 3, responseid: 'meshctrl' })); + } else if (args.sleep) { + // Sleep operation + ws.send(JSON.stringify({ action: 'poweraction', nodeids: nodes, actiontype: 4, responseid: 'meshctrl' })); + } else { + console.log('No power operation specified.'); + process.exit(1); + } + break; + } case 'devicesharing': { if (args.add) { if (args.add.length == 0) { console.log("Invalid guest name."); process.exit(1); } @@ -1544,14 +1590,17 @@ function serverConnect() { case 'createmesh': // ADDDEVICEGROUP case 'deletemesh': // REMOVEDEVICEGROUP case 'editmesh': // EDITDEVICEGROUP + case 'wakedevices': case 'changeDeviceMesh': case 'addmeshuser': // case 'removemeshuser': // + case 'wakedevices': // case 'inviteAgent': // case 'adddeviceuser': // case 'createusergroup': // case 'deleteusergroup': // case 'runcommands': + case 'poweraction': case 'addusertousergroup': case 'removeuserfromusergroup': case 'removeDeviceShare': diff --git a/meshuser.js b/meshuser.js index cc649295..058ad496 100644 --- a/meshuser.js +++ b/meshuser.js @@ -3643,8 +3643,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Perform wake-on-lan for (i in command.nodeids) { + var nodeid = command.nodeids[i]; + + // Argument validation + if (common.validateString(nodeid, 8, 128) == false) { continue; } // Check the nodeid + else if (nodeid.indexOf('/') == -1) { nodeid = 'node/' + domain.id + '/' + nodeid; } + else if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) { continue; } // Invalid domain, operation only valid for current domain + // Get the node and the rights for this node - parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + parent.GetNodeWithRights(domain, user, nodeid, function (node, rights, visible) { // Check we have the rights to delete this device if ((rights & MESHRIGHT_WAKEDEVICE) == 0) return; @@ -3681,8 +3688,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } }); }); + // Confirm we may be doing something (TODO) - try { ws.send(JSON.stringify({ action: 'wakedevices' })); } catch (ex) { } + if (command.responseid != null) { + try { ws.send(JSON.stringify({ action: 'wakedevices', responseid: command.responseid, result: 'ok' })); } catch (ex) { } + } else { + try { ws.send(JSON.stringify({ action: 'wakedevices' })); } catch (ex) { } + } } break; } @@ -3782,8 +3794,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's if (common.validateInt(command.actiontype, 2, 4) == false) break; // Check actiontype for (i in command.nodeids) { + var nodeid = command.nodeids[i]; + + // Argument validation + if (common.validateString(nodeid, 8, 128) == false) { continue; } // Check the nodeid + else if (nodeid.indexOf('/') == -1) { nodeid = 'node/' + domain.id + '/' + nodeid; } + else if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) { continue; } // Invalid domain, operation only valid for current domain + // Get the node and the rights for this node - parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) { + parent.GetNodeWithRights(domain, user, nodeid, function (node, rights, visible) { // Check we have the rights to delete this device if ((rights & MESHRIGHT_RESETOFF) == 0) return; @@ -3798,7 +3817,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use }); // Confirm we may be doing something (TODO) - try { ws.send(JSON.stringify({ action: 'poweraction' })); } catch (ex) { } + if (command.responseid != null) { + try { ws.send(JSON.stringify({ action: 'poweraction', responseid: command.responseid, result: 'ok' })); } catch (ex) { } + } else { + try { ws.send(JSON.stringify({ action: 'poweraction' })); } catch (ex) { } + } } break; } diff --git a/readme.md b/readme.md index 487fde9a..acce1b17 100644 --- a/readme.md +++ b/readme.md @@ -12,9 +12,9 @@ MeshCentral is a full computer management web site. With MeshCentral, you can run your own web server to remotely manage and control computers on a local network or anywhere on the internet. Once you get the server started, create device group and download and install an agent on each computer you want to manage. A minute later, the new computer will show up on the web site and you can take control of it. MeshCentral includes full web-based remote desktop, terminal and file management capability. -To try out this software, please go to [MeshCentral.com](http://meshcentral.com). Be mindful that the public MeshCentral server comes with no guaranties, most should setup their own server +To try out this software on the public server, please visit [MeshCentral.com/login](https://meshcentral.com/login). Be mindful that the public MeshCentral server comes with no guaranties, most should setup their own server. -For more information, [visit MeshCommander.com/MeshCentral2](https://www.meshcommander.com/meshcentral2). +For more information, [visit MeshCentral.com](https://www.meshcentral.com). ## Social Media [Reddit](https://www.reddit.com/r/MeshCentral/)