From fa8680c14e58686e17ebaad79c7ebbd810b1def2 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Sat, 7 May 2022 15:47:50 -0700 Subject: [PATCH] Added RDP viewonly and limited input. --- apprelays.js | 51 ++++++++++++++++++++++++++----- public/scripts/agent-rdp-0.0.1.js | 29 +++++++++++++++++- views/default.handlebars | 6 ++-- 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/apprelays.js b/apprelays.js index 037ff361..18c28ed6 100644 --- a/apprelays.js +++ b/apprelays.js @@ -34,6 +34,29 @@ const PROTOCOL_WEBSSH = 202; const PROTOCOL_WEBSFTP = 203; const PROTOCOL_WEBVNC = 204; +// Mesh Rights +const MESHRIGHT_EDITMESH = 0x00000001; // 1 +const MESHRIGHT_MANAGEUSERS = 0x00000002; // 2 +const MESHRIGHT_MANAGECOMPUTERS = 0x00000004; // 4 +const MESHRIGHT_REMOTECONTROL = 0x00000008; // 8 +const MESHRIGHT_AGENTCONSOLE = 0x00000010; // 16 +const MESHRIGHT_SERVERFILES = 0x00000020; // 32 +const MESHRIGHT_WAKEDEVICE = 0x00000040; // 64 +const MESHRIGHT_SETNOTES = 0x00000080; // 128 +const MESHRIGHT_REMOTEVIEWONLY = 0x00000100; // 256 +const MESHRIGHT_NOTERMINAL = 0x00000200; // 512 +const MESHRIGHT_NOFILES = 0x00000400; // 1024 +const MESHRIGHT_NOAMT = 0x00000800; // 2048 +const MESHRIGHT_DESKLIMITEDINPUT = 0x00001000; // 4096 +const MESHRIGHT_LIMITEVENTS = 0x00002000; // 8192 +const MESHRIGHT_CHATNOTIFY = 0x00004000; // 16384 +const MESHRIGHT_UNINSTALL = 0x00008000; // 32768 +const MESHRIGHT_NODESKTOP = 0x00010000; // 65536 +const MESHRIGHT_REMOTECOMMAND = 0x00020000; // 131072 +const MESHRIGHT_RESETOFF = 0x00040000; // 262144 +const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288 +const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576 +const MESHRIGHT_ADMIN = 0xFFFFFFFF; // Construct a MSTSC Relay object, called upon connection // This implementation does not have TLS support @@ -233,11 +256,12 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) { obj.userid = obj.cookie.userid; } - // Get node - parent.parent.db.Get(obj.nodeid, function (err, nodes) { + // Get node and rights + parent.GetNodeWithRights(domain, obj.userid, obj.nodeid, function (node, rights, visible) { if (obj.ws == null) return; // obj has been cleaned up, just exit. - if ((err != null) || (nodes == null) || (nodes.length != 1)) { obj.close(); return; } - const node = nodes[0]; + if ((node == null) || (visible == false) || ((rights & MESHRIGHT_REMOTECONTROL) == 0)) { obj.close(); return; } + if ((rights != MESHRIGHT_ADMIN) && ((rights & MESHRIGHT_REMOTEVIEWONLY) != 0)) { obj.viewonly = true; } + if ((rights != MESHRIGHT_ADMIN) && ((rights & MESHRIGHT_DESKLIMITEDINPUT) != 0)) { obj.limitedinput = true; } obj.mtype = node.mtype; // Store the device group type obj.meshid = node.meshid; // Store the MeshID @@ -287,10 +311,21 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) { }); break; } - case 'mouse': { if (rdpClient) { rdpClient.sendPointerEvent(msg[1], msg[2], msg[3], msg[4]); } break; } - case 'wheel': { if (rdpClient) { rdpClient.sendWheelEvent(msg[1], msg[2], msg[3], msg[4]); } break; } - case 'scancode': { if (rdpClient) { rdpClient.sendKeyEventScancode(msg[1], msg[2]); } break; } - case 'unicode': { if (rdpClient) { rdpClient.sendKeyEventUnicode(msg[1], msg[2]); } break; } + case 'mouse': { if (rdpClient && (obj.viewonly != true)) { rdpClient.sendPointerEvent(msg[1], msg[2], msg[3], msg[4]); } break; } + case 'wheel': { if (rdpClient && (obj.viewonly != true)) { rdpClient.sendWheelEvent(msg[1], msg[2], msg[3], msg[4]); } break; } + case 'scancode': { + if (obj.limitedinput == true) { // Limit keyboard input + var ok = false, k = msg[1]; + if ((k >= 2) && (k <= 11)) { ok = true; } // Number keys 1 to 0 + if ((k >= 16) && (k <= 25)) { ok = true; } // First keyboard row + if ((k >= 30) && (k <= 38)) { ok = true; } // Second keyboard row + if ((k >= 44) && (k <= 50)) { ok = true; } // Third keyboard row + if ((k == 14) || (k == 28)) { ok = true; } // Enter and backspace + if (ok == false) return; + } + if (rdpClient && (obj.viewonly != true)) { rdpClient.sendKeyEventScancode(msg[1], msg[2]); } break; + } + case 'unicode': { if (rdpClient && (obj.viewonly != true)) { rdpClient.sendKeyEventUnicode(msg[1], msg[2]); } break; } case 'utype': { if (!rdpClient) return; obj.utype = msg[1]; diff --git a/public/scripts/agent-rdp-0.0.1.js b/public/scripts/agent-rdp-0.0.1.js index f65e3813..7fbc3f7c 100644 --- a/public/scripts/agent-rdp-0.0.1.js +++ b/public/scripts/agent-rdp-0.0.1.js @@ -7,7 +7,7 @@ // Construct a RDP remote desktop object var CreateRDPDesktop = function (canvasid) { var obj = {} - obj.m = {}; + obj.m = { KeyAction: { "NONE": 0, "DOWN": 1, "UP": 2, "SCROLL": 3, "EXUP": 4, "EXDOWN": 5, "DBLCLICK": 6 } }; obj.State = 0; obj.canvas = Q(canvasid); obj.CanvasId = canvasid; @@ -153,12 +153,14 @@ var CreateRDPDesktop = function (canvasid) { } obj.m.handleKeyUp = function (e) { if (!obj.socket || (obj.State != 3)) return; + console.log('handleKeyUp', Mstsc.scancode(e)); obj.socket.send(JSON.stringify(['scancode', Mstsc.scancode(e), false])); e.preventDefault(); return false; } obj.m.handleKeyDown = function (e) { if (!obj.socket || (obj.State != 3)) return; + console.log('handleKeyDown', Mstsc.scancode(e)); obj.socket.send(JSON.stringify(['scancode', Mstsc.scancode(e), true])); e.preventDefault(); return false; @@ -178,6 +180,31 @@ var CreateRDPDesktop = function (canvasid) { if (!obj.socket || (obj.State != 3)) return; obj.socket.send(JSON.stringify(['utype', txt])); } + obj.m.SendKeyMsgKC = function (action, kc, extendedKey) { + if (obj.State != 3) return; + + console.log('SendKeyMsgKC', action); + + /* + if (typeof action == 'object') { for (var i in action) { obj.m.SendKeyMsgKC(action[i][0], action[i][1], action[i][2]); } } + else { + console.log(action, kc, extendedKey); + obj.socket.send(JSON.stringify(['scancode', kc, (action == 1)])); + + if (action == 1) { // Key Down + if (obj.pressedKeys.indexOf(kc) == -1) { obj.pressedKeys.unshift(kc); } // Add key press to start of array + } else if (action == 2) { // Key Up + var i = obj.pressedKeys.indexOf(kc); + if (i != -1) { obj.pressedKeys.splice(i, 1); } // Remove the key press from the pressed array + } + if (obj.debugmode > 0) { console.log('Sending Key ' + kc + ', action ' + action); } + + var up = (action - 1); + if (extendedKey) { if (up == 1) { up = 3; } else { up = 4; } } + obj.send(String.fromCharCode(0x00, obj.InputType.KEY, 0x00, 0x06, up, kc)); + } + */ + } obj.m.mousedblclick = function () { } obj.m.handleKeyPress = function () { } obj.m.setRotation = function () { } diff --git a/views/default.handlebars b/views/default.handlebars index 024d7ddf..999b08a3 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -8330,12 +8330,12 @@ QV('DeskClip', (inputAllowed) && (currentNode.agent) && ((features2 & 0x1800) != 0x1800) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && ((desktop == null) || (desktop.contype != 2)) && ((desktopsettings.autoclipboard != true) || (navigator.clipboard == null) || (navigator.clipboard.readText == null))); // Clipboard not supported on macOS QE('DeskESC', (deskState == 3) && (desktop.contype != 4)); QV('DeskESC', browserfullscreen && inputAllowed); - QE('DeskType', (deskState == 3)); // && (desktop.contype != 4) + QE('DeskType', deskState == 3); QV('DeskType', inputAllowed); - QE('DeskWD', (deskState == 3) && (desktop.contype != 4)); + QE('DeskWD', deskState == 3); QV('DeskWD', inputAllowed); QV('deskkeys', inputAllowed); - QE('deskkeys', (desktop != null) && (desktop.contype != 4)); + QE('deskkeys', desktop != null); QV('DeskTimer', deskState == 3); // Enable browser clipboard read if supported