Added relay right and fixed relay permissions (#4682)

Ylian Saint-Hilaire committed Nov 1, 2022 at 16:05 UTC e74a3081139e7fb9d68e342cd84e23818ec97d21
6 files changed +75 -59
apprelays.js
+24 -23
@@ -35,28 +35,29 @@ const PROTOCOL_WEBSFTP = 203;
35 const PROTOCOL_WEBVNC = 204;
36
37 // Mesh Rights
38 -const MESHRIGHT_EDITMESH = 0x00000001; // 1
39 -const MESHRIGHT_MANAGEUSERS = 0x00000002; // 2
40 -const MESHRIGHT_MANAGECOMPUTERS = 0x00000004; // 4
41 -const MESHRIGHT_REMOTECONTROL = 0x00000008; // 8
42 -const MESHRIGHT_AGENTCONSOLE = 0x00000010; // 16
43 -const MESHRIGHT_SERVERFILES = 0x00000020; // 32
44 -const MESHRIGHT_WAKEDEVICE = 0x00000040; // 64
45 -const MESHRIGHT_SETNOTES = 0x00000080; // 128
46 -const MESHRIGHT_REMOTEVIEWONLY = 0x00000100; // 256
47 -const MESHRIGHT_NOTERMINAL = 0x00000200; // 512
48 -const MESHRIGHT_NOFILES = 0x00000400; // 1024
49 -const MESHRIGHT_NOAMT = 0x00000800; // 2048
50 -const MESHRIGHT_DESKLIMITEDINPUT = 0x00001000; // 4096
51 -const MESHRIGHT_LIMITEVENTS = 0x00002000; // 8192
52 -const MESHRIGHT_CHATNOTIFY = 0x00004000; // 16384
53 -const MESHRIGHT_UNINSTALL = 0x00008000; // 32768
54 -const MESHRIGHT_NODESKTOP = 0x00010000; // 65536
55 -const MESHRIGHT_REMOTECOMMAND = 0x00020000; // 131072
56 -const MESHRIGHT_RESETOFF = 0x00040000; // 262144
57 -const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
58 -const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
59 -const MESHRIGHT_ADMIN = 0xFFFFFFFF;
38 +const MESHRIGHT_EDITMESH = 0x00000001; // 1
39 +const MESHRIGHT_MANAGEUSERS = 0x00000002; // 2
40 +const MESHRIGHT_MANAGECOMPUTERS = 0x00000004; // 4
41 +const MESHRIGHT_REMOTECONTROL = 0x00000008; // 8
42 +const MESHRIGHT_AGENTCONSOLE = 0x00000010; // 16
43 +const MESHRIGHT_SERVERFILES = 0x00000020; // 32
44 +const MESHRIGHT_WAKEDEVICE = 0x00000040; // 64
45 +const MESHRIGHT_SETNOTES = 0x00000080; // 128
46 +const MESHRIGHT_REMOTEVIEWONLY = 0x00000100; // 256
47 +const MESHRIGHT_NOTERMINAL = 0x00000200; // 512
48 +const MESHRIGHT_NOFILES = 0x00000400; // 1024
49 +const MESHRIGHT_NOAMT = 0x00000800; // 2048
50 +const MESHRIGHT_DESKLIMITEDINPUT = 0x00001000; // 4096
51 +const MESHRIGHT_LIMITEVENTS = 0x00002000; // 8192
52 +const MESHRIGHT_CHATNOTIFY = 0x00004000; // 16384
53 +const MESHRIGHT_UNINSTALL = 0x00008000; // 32768
54 +const MESHRIGHT_NODESKTOP = 0x00010000; // 65536
55 +const MESHRIGHT_REMOTECOMMAND = 0x00020000; // 131072
56 +const MESHRIGHT_RESETOFF = 0x00040000; // 262144
57 +const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
58 +const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
59 +const MESHRIGHT_RELAY = 0x00200000; // 2097152
60 +const MESHRIGHT_ADMIN = 0xFFFFFFFF;
61
62 // SerialTunnel object is used to embed TLS within another connection.
63 function SerialTunnel(options) {
@@ -2332,6 +2333,6 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
2333 function checkRelayRights(parent, domain, user, relayNodeId, func) {
2334 if (relayNodeId == null) { func(true); return; } // No relay, do nothing.
2335 parent.GetNodeWithRights(domain, user, relayNodeId, function (node, rights, visible) {
2335 - func((node != null) && (rights == 0xFFFFFFFF));
2336 + func((node != null) && ((rights & 0x00200008) != 0)); // MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights
2337 });
2338 }
meshrelay.js
+33 -31
@@ -14,27 +14,29 @@
14 "use strict";
15
16 // Mesh Rights
17 -const MESHRIGHT_EDITMESH = 0x00000001;
18 -const MESHRIGHT_MANAGEUSERS = 0x00000002;
19 -const MESHRIGHT_MANAGECOMPUTERS = 0x00000004;
20 -const MESHRIGHT_REMOTECONTROL = 0x00000008;
21 -const MESHRIGHT_AGENTCONSOLE = 0x00000010;
22 -const MESHRIGHT_SERVERFILES = 0x00000020;
23 -const MESHRIGHT_WAKEDEVICE = 0x00000040;
24 -const MESHRIGHT_SETNOTES = 0x00000080;
25 -const MESHRIGHT_REMOTEVIEWONLY = 0x00000100;
26 -const MESHRIGHT_NOTERMINAL = 0x00000200;
27 -const MESHRIGHT_NOFILES = 0x00000400;
28 -const MESHRIGHT_NOAMT = 0x00000800;
29 -const MESHRIGHT_DESKLIMITEDINPUT = 0x00001000;
30 -const MESHRIGHT_LIMITEVENTS = 0x00002000;
31 -const MESHRIGHT_CHATNOTIFY = 0x00004000;
32 -const MESHRIGHT_UNINSTALL = 0x00008000;
33 -const MESHRIGHT_NODESKTOP = 0x00010000;
34 -const MESHRIGHT_REMOTECOMMAND = 0x00020000;
35 -const MESHRIGHT_RESETOFF = 0x00040000;
36 -const MESHRIGHT_GUESTSHARING = 0x00080000;
37 -const MESHRIGHT_ADMIN = 0xFFFFFFFF;
17 +const MESHRIGHT_EDITMESH = 0x00000001; // 1
18 +const MESHRIGHT_MANAGEUSERS = 0x00000002; // 2
19 +const MESHRIGHT_MANAGECOMPUTERS = 0x00000004; // 4
20 +const MESHRIGHT_REMOTECONTROL = 0x00000008; // 8
21 +const MESHRIGHT_AGENTCONSOLE = 0x00000010; // 16
22 +const MESHRIGHT_SERVERFILES = 0x00000020; // 32
23 +const MESHRIGHT_WAKEDEVICE = 0x00000040; // 64
24 +const MESHRIGHT_SETNOTES = 0x00000080; // 128
25 +const MESHRIGHT_REMOTEVIEWONLY = 0x00000100; // 256
26 +const MESHRIGHT_NOTERMINAL = 0x00000200; // 512
27 +const MESHRIGHT_NOFILES = 0x00000400; // 1024
28 +const MESHRIGHT_NOAMT = 0x00000800; // 2048
29 +const MESHRIGHT_DESKLIMITEDINPUT = 0x00001000; // 4096
30 +const MESHRIGHT_LIMITEVENTS = 0x00002000; // 8192
31 +const MESHRIGHT_CHATNOTIFY = 0x00004000; // 16384
32 +const MESHRIGHT_UNINSTALL = 0x00008000; // 32768
33 +const MESHRIGHT_NODESKTOP = 0x00010000; // 65536
34 +const MESHRIGHT_REMOTECOMMAND = 0x00020000; // 131072
35 +const MESHRIGHT_RESETOFF = 0x00040000; // 262144
36 +const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
37 +const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
38 +const MESHRIGHT_RELAY = 0x00200000; // 2097152
39 +const MESHRIGHT_ADMIN = 0xFFFFFFFF;
40
41 // Protocol:
42 // 1 = Terminal
@@ -868,8 +870,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
870 if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
871 const node = docs[0];
872
871 - // Check if this user has permission to manage this computer
872 - if ((obj.nouser !== true) && ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0)) { console.log('ERR: Access denied (1)'); try { obj.close(); } catch (e) { } return; }
873 + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights)
874 + if ((obj.nouser !== true) && ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0)) { console.log('ERR: Access denied (1)'); try { obj.close(); } catch (ex) { } return; }
875
876 // Set nodeid and meshid
877 obj.nodeid = node._id;
@@ -907,8 +909,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
909 if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
910 const node = docs[0];
911
910 - // Check if this user has permission to manage this computer
911 - if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; }
912 + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights)
913 + if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; }
914
915 // Set nodeid and meshid
916 obj.nodeid = node._id;
@@ -963,8 +965,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
965 if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
966 const node = docs[0];
967
966 - // Check if this user has permission to manage this computer
967 - if ((obj.nouser !== true) && ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0)) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; }
968 + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights)
969 + if ((obj.nouser !== true) && ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0)) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; }
970
971 // Set nodeid and meshid
972 obj.nodeid = node._id;
@@ -1017,8 +1019,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
1019 if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
1020 const node = docs[0];
1021
1020 - // Check if this user has permission to manage this computer
1021 - if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; }
1022 + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights)
1023 + if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; }
1024
1025 // Set nodeid and meshid
1026 obj.nodeid = node._id;
@@ -1263,8 +1265,8 @@ function CreateLocalRelayEx(parent, ws, req, domain, user, cookie) {
1265 obj.host = node.host;
1266 obj.meshid = node.meshid;
1267
1266 - // Check if this user has permission to manage this computer
1267 - if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; }
1268 + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights)
1269 + if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; }
1270
1271 // Setup TCP client
1272 obj.client = new net.Socket();
meshuser.js
+1
@@ -52,6 +52,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
52 const MESHRIGHT_RESETOFF = 0x00040000; // 262144
53 const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
54 const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
55 + const MESHRIGHT_RELAY = 0x00200000; // 2097152
56 const MESHRIGHT_ADMIN = 0xFFFFFFFF;
57
58 // Site rights
views/default.handlebars
+13 -1
@@ -7762,6 +7762,9 @@
7762 if (rights & 32768) str.push("Uninstall");
7763 if (rights & 131072) str.push("Commands");
7764 if (rights & 262144) str.push("Reset/Off");
7765 + if (rights & 524288) str.push("Sharing");
7766 + if (rights & 1048576) str.push("Details");
7767 + if (rights & 2097152) str.push("Relay");
7768 if (str.length == 0) return "No Rights";
7769 return str.join(', ');
7770 }
@@ -7792,6 +7795,9 @@
7795 if (rights & 32768) str.push("Uninstall");
7796 if (rights & 131072) str.push("Commands");
7797 if (rights & 262144) str.push("Reset/Off");
7798 + if (rights & 524288) str.push("Sharing");
7799 + if (rights & 1048576) str.push("Details");
7800 + if (rights & 2097152) str.push("Relay");
7801 if (str.length == 0) return "No Rights";
7802 return str.join(', ');
7803 }
@@ -13234,7 +13240,7 @@
13240 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>' + "Manage Device Group Users" + '</label><br>';
13241 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>' + "Manage Device Group Computers" + '</label><br>';
13242 }
13237 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "Remote Control" + '</label><br>';
13243 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "Remote Control & Relay" + '</label><br>';
13244 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>' + "Remote View Only" + '</label><br>';
13245 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>' + "Limited Input Only" + '</label><br>';
13246 if (serverinfo.guestdevicesharing !== false) { x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20guestshare style=margin-left:12px>' + "Guest Sharing" + '</label><br>'; }
@@ -13252,6 +13258,7 @@
13258 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20commands>' + "Remote Commands" + '</label><br>';
13259 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20resetoff>' + "Reset / Power Off" + '</label><br>';
13260 x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20details>' + "Device Details" + '</label><br>';
13261 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20relay>' + "Use as Relay" + '</label><br>';
13262 x += '</div>';
13263
13264 if (userid == null) {
@@ -13329,6 +13336,7 @@
13336 if (urights & 262144) { Q('p20resetoff').checked = true; }
13337 if ((urights & 524288) && (serverinfo.guestdevicesharing !== false)) { Q('p20guestshare').checked = true; }
13338 if (urights & 1048576) { Q('p20details').checked = true; }
13339 + if (urights & 2097152) { Q('p20relay').checked = true; }
13340 }
13341
13342 p20validateAddMeshUserDialog(userid);
@@ -13377,6 +13385,7 @@
13385 Q('p20resetoff').checked = ((devrights & 262144) != 0);
13386 if (serverinfo.guestdevicesharing !== false) { Q('p20guestshare').checked = ((devrights & 524288) != 0); }
13387 Q('p20details').checked = ((devrights & 1048576) != 0);
13388 + Q('p20relay').checked = ((devrights & 2097152) != 0);
13389 ok = (nodeid != '');
13390 }
13391
@@ -13458,6 +13467,7 @@
13467 QE('p20commands', nc);
13468 QE('p20resetoff', nc);
13469 QE('p20details', nc);
13470 + QE('p20relay', nc);
13471 }
13472
13473 function p20showAddMeshUserDialogEx(b, t) {
@@ -13487,6 +13497,7 @@
13497 if (Q('p20resetoff').checked == true) meshadmin += 262144;
13498 if ((serverinfo.guestdevicesharing !== false) && (Q('p20guestshare').checked == true) && (Q('p20remoteview').checked || (!Q('p20remoteview').checked && !Q('p20remotelimitedinput').checked))) meshadmin += 524288;
13499 if (Q('p20details').checked == true) meshadmin += 1048576;
13500 + if (Q('p20relay').checked == true) meshadmin += 2097152;
13501 }
13502
13503 // Clean up incorrect rights. If Remote Control is not selected, remove flags that don't make sense.
@@ -13572,6 +13583,7 @@
13583 if ((meshrights & 262144) != 0) r.push("Reset/Off");
13584 if ((meshrights & 524288) != 0) r.push("Sharing");
13585 if ((meshrights & 1048576) != 0) r.push("Details");
13586 + if ((meshrights & 2097152) != 0) r.push("Relay");
13587 }
13588 if (r.length == 0) { r.push("No Rights"); }
13589 var uname = xuserid.split('/')[2];
webrelayserver.js
+2 -2
@@ -252,8 +252,8 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates,
252
253 // Check that the user has rights to access this device
254 parent.webserver.GetNodeWithRights(domain, userid, nodeid, function (node, rights, visible) {
255 - // If there is no remote control rights, reject this web relay
256 - if ((rights & 8) == 0) { res.sendStatus(404); return; }
255 + // If there is no remote control or relay rights, reject this web relay
256 + if ((rights & 0x00200008) == 0) { res.sendStatus(404); return; } // MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY
257
258 // There is a relay session, but it's not correct, close it.
259 if (xrelaySession != null) { xrelaySession.close(); delete relaySessions[webSessionId]; }
webserver.js
+2 -2
@@ -6845,8 +6845,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
6845
6846 // Check that the user has rights to access this device
6847 parent.webserver.GetNodeWithRights(domain, userid, nodeid, function (node, rights, visible) {
6848 - // If there is no remote control rights, reject this web relay
6849 - if ((rights & 8) == 0) { res.sendStatus(404); return; }
6848 + // If there is no remote control or relay rights, reject this web relay
6849 + if ((rights & 0x00200008) == 0) { res.sendStatus(404); return; } // MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY
6850
6851 // Check if there is a free relay DNS name we can use
6852 var selectedHost = null;