diff --git a/apprelays.js b/apprelays.js index a61948fc..7f5444c5 100644 --- a/apprelays.js +++ b/apprelays.js @@ -35,28 +35,29 @@ 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; +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_RELAY = 0x00200000; // 2097152 +const MESHRIGHT_ADMIN = 0xFFFFFFFF; // SerialTunnel object is used to embed TLS within another connection. function SerialTunnel(options) { @@ -2332,6 +2333,6 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user function checkRelayRights(parent, domain, user, relayNodeId, func) { if (relayNodeId == null) { func(true); return; } // No relay, do nothing. parent.GetNodeWithRights(domain, user, relayNodeId, function (node, rights, visible) { - func((node != null) && (rights == 0xFFFFFFFF)); + func((node != null) && ((rights & 0x00200008) != 0)); // MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights }); } diff --git a/meshrelay.js b/meshrelay.js index 3ad8f903..559bf23a 100644 --- a/meshrelay.js +++ b/meshrelay.js @@ -14,27 +14,29 @@ "use strict"; // Mesh Rights -const MESHRIGHT_EDITMESH = 0x00000001; -const MESHRIGHT_MANAGEUSERS = 0x00000002; -const MESHRIGHT_MANAGECOMPUTERS = 0x00000004; -const MESHRIGHT_REMOTECONTROL = 0x00000008; -const MESHRIGHT_AGENTCONSOLE = 0x00000010; -const MESHRIGHT_SERVERFILES = 0x00000020; -const MESHRIGHT_WAKEDEVICE = 0x00000040; -const MESHRIGHT_SETNOTES = 0x00000080; -const MESHRIGHT_REMOTEVIEWONLY = 0x00000100; -const MESHRIGHT_NOTERMINAL = 0x00000200; -const MESHRIGHT_NOFILES = 0x00000400; -const MESHRIGHT_NOAMT = 0x00000800; -const MESHRIGHT_DESKLIMITEDINPUT = 0x00001000; -const MESHRIGHT_LIMITEVENTS = 0x00002000; -const MESHRIGHT_CHATNOTIFY = 0x00004000; -const MESHRIGHT_UNINSTALL = 0x00008000; -const MESHRIGHT_NODESKTOP = 0x00010000; -const MESHRIGHT_REMOTECOMMAND = 0x00020000; -const MESHRIGHT_RESETOFF = 0x00040000; -const MESHRIGHT_GUESTSHARING = 0x00080000; -const MESHRIGHT_ADMIN = 0xFFFFFFFF; +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_RELAY = 0x00200000; // 2097152 +const MESHRIGHT_ADMIN = 0xFFFFFFFF; // Protocol: // 1 = Terminal @@ -868,8 +870,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket const node = docs[0]; - // Check if this user has permission to manage this computer - 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; } + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights) + 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; } // Set nodeid and meshid obj.nodeid = node._id; @@ -907,8 +909,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket const node = docs[0]; - // Check if this user has permission to manage this computer - if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; } + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights) + if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; } // Set nodeid and meshid obj.nodeid = node._id; @@ -963,8 +965,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket const node = docs[0]; - // Check if this user has permission to manage this computer - 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; } + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights) + 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; } // Set nodeid and meshid obj.nodeid = node._id; @@ -1017,8 +1019,8 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket const node = docs[0]; - // Check if this user has permission to manage this computer - if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; } + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights) + if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; } // Set nodeid and meshid obj.nodeid = node._id; @@ -1263,8 +1265,8 @@ function CreateLocalRelayEx(parent, ws, req, domain, user, cookie) { obj.host = node.host; obj.meshid = node.meshid; - // Check if this user has permission to manage this computer - if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; } + // Check if this user has permission to relay thru this computer (MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY rights) + if ((parent.GetNodeRights(obj.user, node.meshid, node._id) & 0x00200008) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (ex) { } return; } // Setup TCP client obj.client = new net.Socket(); diff --git a/meshuser.js b/meshuser.js index f3c36a07..40f035af 100644 --- a/meshuser.js +++ b/meshuser.js @@ -52,6 +52,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use const MESHRIGHT_RESETOFF = 0x00040000; // 262144 const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288 const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576 + const MESHRIGHT_RELAY = 0x00200000; // 2097152 const MESHRIGHT_ADMIN = 0xFFFFFFFF; // Site rights diff --git a/views/default.handlebars b/views/default.handlebars index 79dbcd16..bf3317d5 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -7762,6 +7762,9 @@ if (rights & 32768) str.push("Uninstall"); if (rights & 131072) str.push("Commands"); if (rights & 262144) str.push("Reset/Off"); + if (rights & 524288) str.push("Sharing"); + if (rights & 1048576) str.push("Details"); + if (rights & 2097152) str.push("Relay"); if (str.length == 0) return "No Rights"; return str.join(', '); } @@ -7792,6 +7795,9 @@ if (rights & 32768) str.push("Uninstall"); if (rights & 131072) str.push("Commands"); if (rights & 262144) str.push("Reset/Off"); + if (rights & 524288) str.push("Sharing"); + if (rights & 1048576) str.push("Details"); + if (rights & 2097152) str.push("Relay"); if (str.length == 0) return "No Rights"; return str.join(', '); } @@ -13234,7 +13240,7 @@ x += '
'; x += '
'; } - x += '
'; + x += '
'; x += '
'; x += '
'; if (serverinfo.guestdevicesharing !== false) { x += '
'; } @@ -13252,6 +13258,7 @@ x += '
'; x += '
'; x += '
'; + x += '
'; x += ''; if (userid == null) { @@ -13329,6 +13336,7 @@ if (urights & 262144) { Q('p20resetoff').checked = true; } if ((urights & 524288) && (serverinfo.guestdevicesharing !== false)) { Q('p20guestshare').checked = true; } if (urights & 1048576) { Q('p20details').checked = true; } + if (urights & 2097152) { Q('p20relay').checked = true; } } p20validateAddMeshUserDialog(userid); @@ -13377,6 +13385,7 @@ Q('p20resetoff').checked = ((devrights & 262144) != 0); if (serverinfo.guestdevicesharing !== false) { Q('p20guestshare').checked = ((devrights & 524288) != 0); } Q('p20details').checked = ((devrights & 1048576) != 0); + Q('p20relay').checked = ((devrights & 2097152) != 0); ok = (nodeid != ''); } @@ -13458,6 +13467,7 @@ QE('p20commands', nc); QE('p20resetoff', nc); QE('p20details', nc); + QE('p20relay', nc); } function p20showAddMeshUserDialogEx(b, t) { @@ -13487,6 +13497,7 @@ if (Q('p20resetoff').checked == true) meshadmin += 262144; if ((serverinfo.guestdevicesharing !== false) && (Q('p20guestshare').checked == true) && (Q('p20remoteview').checked || (!Q('p20remoteview').checked && !Q('p20remotelimitedinput').checked))) meshadmin += 524288; if (Q('p20details').checked == true) meshadmin += 1048576; + if (Q('p20relay').checked == true) meshadmin += 2097152; } // Clean up incorrect rights. If Remote Control is not selected, remove flags that don't make sense. @@ -13572,6 +13583,7 @@ if ((meshrights & 262144) != 0) r.push("Reset/Off"); if ((meshrights & 524288) != 0) r.push("Sharing"); if ((meshrights & 1048576) != 0) r.push("Details"); + if ((meshrights & 2097152) != 0) r.push("Relay"); } if (r.length == 0) { r.push("No Rights"); } var uname = xuserid.split('/')[2]; diff --git a/webrelayserver.js b/webrelayserver.js index 900877a9..a7a967ae 100644 --- a/webrelayserver.js +++ b/webrelayserver.js @@ -252,8 +252,8 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates, // Check that the user has rights to access this device parent.webserver.GetNodeWithRights(domain, userid, nodeid, function (node, rights, visible) { - // If there is no remote control rights, reject this web relay - if ((rights & 8) == 0) { res.sendStatus(404); return; } + // If there is no remote control or relay rights, reject this web relay + if ((rights & 0x00200008) == 0) { res.sendStatus(404); return; } // MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY // There is a relay session, but it's not correct, close it. if (xrelaySession != null) { xrelaySession.close(); delete relaySessions[webSessionId]; } diff --git a/webserver.js b/webserver.js index ba31b2c6..5219c169 100644 --- a/webserver.js +++ b/webserver.js @@ -6845,8 +6845,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF // Check that the user has rights to access this device parent.webserver.GetNodeWithRights(domain, userid, nodeid, function (node, rights, visible) { - // If there is no remote control rights, reject this web relay - if ((rights & 8) == 0) { res.sendStatus(404); return; } + // If there is no remote control or relay rights, reject this web relay + if ((rights & 0x00200008) == 0) { res.sendStatus(404); return; } // MESHRIGHT_REMOTECONTROL or MESHRIGHT_RELAY // Check if there is a free relay DNS name we can use var selectedHost = null;