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;