Completed user access rights removal feature, #3065

This commit is contained in:
Ylian Saint-Hilaire 2021-08-27 14:42:28 -07:00
parent 96f7c048f7
commit 41ecece9a9
6 changed files with 104 additions and 30 deletions

View File

@ -874,6 +874,7 @@ function handleServerCommand(data) {
case 'msg': { case 'msg': {
switch (data.type) { switch (data.type) {
case 'console': { // Process a console command case 'console': { // Process a console command
if ((typeof data.rights != 'number') || ((data.rights & 16) == 0)) break; // Check console rights
if (data.value && data.sessionid) { if (data.value && data.sessionid) {
MeshServerLogEx(17, [data.value], "Processing console command: " + data.value, data); MeshServerLogEx(17, [data.value], "Processing console command: " + data.value, data);
var args = splitArgs(data.value); var args = splitArgs(data.value);

View File

@ -911,6 +911,7 @@ require('MeshAgent').AddCommandHandler(function (data) {
{ {
switch (data.type) { switch (data.type) {
case 'console': { // Process a console command case 'console': { // Process a console command
if ((typeof data.rights != 'number') || ((data.rights & 16) == 0)) break; // Check console rights
if (data.value && data.sessionid) { if (data.value && data.sessionid) {
var args = splitArgs(data.value); var args = splitArgs(data.value);
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid); processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);

View File

@ -4313,7 +4313,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Get the node and the rights for this node // Get the node and the rights for this node
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return; if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
// Ask for clipboard data from agent // Ask for clipboard data from agent
var agent = parent.wsagents[node._id]; var agent = parent.wsagents[node._id];
@ -4326,7 +4326,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Get the node and the rights for this node // Get the node and the rights for this node
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return; if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
// Send clipboard data to the agent // Send clipboard data to the agent
var agent = parent.wsagents[node._id]; var agent = parent.wsagents[node._id];

View File

@ -3549,7 +3549,7 @@
if ((currentDevicePanel != 5) && if ((currentDevicePanel != 5) &&
(currentNode != null) && (currentNode != null) &&
((meshrights & 8) || (meshrights & 256)) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 65536) == 0)) && ((meshrights & 8) || (meshrights & 256)) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0)) &&
(((currentNode.agent == null) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 2))) (((currentNode.agent == null) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 2)))
) { menus.push({ n: "Terminal", f: 'setupDeviceMenu(5)' }); } ) { menus.push({ n: "Terminal", f: 'setupDeviceMenu(5)' }); }
@ -6359,6 +6359,28 @@
// These must match server // These must match server
// //
// Remove user rights
function removeUserRights(rights, userid) {
if ((userid != userinfo._id) || (userinfo.removeRights == null)) return rights;
var add = 0, substract = 0;
if ((userinfo.removeRights & 0x00010000) != 0) { add += 0x00010000; } // No Desktop
if ((userinfo.removeRights & 0x00000100) != 0) { add += 0x00000100; } // Desktop View Only
if ((userinfo.removeRights & 0x00000200) != 0) { add += 0x00000200; } // No Terminal
if ((userinfo.removeRights & 0x00000400) != 0) { add += 0x00000400; } // No Files
if ((userinfo.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
if (rights != 0xFFFFFFFF) {
// If not administrator, add and subsctract restrictions
rights |= add;
rights &= (0xFFFFFFFF - substract);
} else {
// If administrator for a device group, start with permissions and add and subsctract restrictions
rights = 1 + 2 + 4 + 8 + 32 + 64 + 128 + 16384 + 32768 + 131072 + 262144 + 524288 + 1048576;
rights |= add;
rights &= (0xFFFFFFFF - substract);
}
return rights;
}
// Get the right of a user on a given device group // Get the right of a user on a given device group
function GetMeshRights(mesh, userid) { function GetMeshRights(mesh, userid) {
if (mesh == null) { return 0; } if (mesh == null) { return 0; }
@ -6367,12 +6389,12 @@
if ((mesh == null) || (mesh.links == null)) { return 0; } if ((mesh == null) || (mesh.links == null)) { return 0; }
// Check if super user // Check if super user
if (userinfo.manageAllDeviceGroups && (userid == userinfo._id)) return 0xFFFFFFFF; if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return removeUserRights(0xFFFFFFFF, userid);
// Check device group link permission // Check device group link permission
var rights = 0, r = mesh.links[userid]; var rights = 0, r = mesh.links[userid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here. if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a device group link, stop here.
rights = r.rights; rights = r.rights;
} }
@ -6384,14 +6406,14 @@
if (i.startsWith('ugrp/')) { if (i.startsWith('ugrp/')) {
r = mesh.links[i]; r = mesh.links[i];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here. if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a user group, stop here.
rights |= r.rights; // TODO: Deal with reverse permissions rights |= r.rights; // TODO: Deal with reverse permissions
} }
} }
} }
} }
return rights; return removeUserRights(rights, userid);
} }
// Returns true if the user can view the given device group // Returns true if the user can view the given device group
@ -6403,7 +6425,7 @@
if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link
// Check if user user // Check if user user
if (userinfo.manageAllDeviceGroups && (userid == userinfo._id)) return true; if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return true;
// Check permissions thru user groups // Check permissions thru user groups
var user = null; var user = null;
@ -6423,8 +6445,7 @@
if (userid == null) { userid = userinfo._id; } if (userid == null) { userid = userinfo._id; }
if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
var r = GetMeshRights(node.meshid, userid); var r = GetMeshRights(node.meshid, userid);
if (r == 0xFFFFFFFF) return r; if (r == 0xFFFFFFFF) return removeUserRights(r, userid);
var user = null;
// Check direct device rights using device data // Check direct device rights using device data
if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions
@ -6438,6 +6459,7 @@
// Check direct device rights using user data // Check direct device rights using user data
/* /*
var user = null;
if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } } if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } }
if ((user != null) && (user.links != null)) { if ((user != null) && (user.links != null)) {
var r2 = user.links[node._id]; var r2 = user.links[node._id];
@ -6447,7 +6469,7 @@
} }
} }
*/ */
return r; return removeUserRights(r, userid);
} }
// Return true if the device is visible to the user // Return true if the device is visible to the user
@ -6468,6 +6490,7 @@
return false; return false;
} }
// //
// Generic Methods // Generic Methods
// //

View File

@ -2807,10 +2807,12 @@
if (userinfo._id == message.event.account._id) { if (userinfo._id == message.event.account._id) {
var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0; var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0; var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
var newRemoveRights = message.event.account.removeRights?message.event.account.removeRights:0;
var oldRemoveRights = userinfo.removeRights?userinfo.removeRights:0;
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); } if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
var oldgroups = userinfo.groups; var oldgroups = userinfo.groups;
userinfo = message.event.account; userinfo = message.event.account;
if ((oldsiteadmin != newsiteadmin) || (message.event.accountImageChange == 1)) { // If the site admin permission or user image has changed... if ((oldsiteadmin != newsiteadmin) || (oldRemoveRights != newRemoveRights) || (message.event.accountImageChange == 1)) { // If the site admin permission or user image has changed...
if (message.event.accountImageChange == 1) { userinfo.accountImageRnd = Math.floor(Math.random() * 9999999999); } if (message.event.accountImageChange == 1) { userinfo.accountImageRnd = Math.floor(Math.random() * 9999999999); }
updateSiteAdmin(); updateSiteAdmin();
} }
@ -15819,6 +15821,28 @@
// These must match server // These must match server
// //
// Remove user rights
function removeUserRights(rights, userid) {
if ((userid != userinfo._id) || (userinfo.removeRights == null)) return rights;
var add = 0, substract = 0;
if ((userinfo.removeRights & 0x00010000) != 0) { add += 0x00010000; } // No Desktop
if ((userinfo.removeRights & 0x00000100) != 0) { add += 0x00000100; } // Desktop View Only
if ((userinfo.removeRights & 0x00000200) != 0) { add += 0x00000200; } // No Terminal
if ((userinfo.removeRights & 0x00000400) != 0) { add += 0x00000400; } // No Files
if ((userinfo.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
if (rights != 0xFFFFFFFF) {
// If not administrator, add and subsctract restrictions
rights |= add;
rights &= (0xFFFFFFFF - substract);
} else {
// If administrator for a device group, start with permissions and add and subsctract restrictions
rights = 1 + 2 + 4 + 8 + 32 + 64 + 128 + 16384 + 32768 + 131072 + 262144 + 524288 + 1048576;
rights |= add;
rights &= (0xFFFFFFFF - substract);
}
return rights;
}
// Get the right of a user on a given device group // Get the right of a user on a given device group
function GetMeshRights(mesh, userid) { function GetMeshRights(mesh, userid) {
if (mesh == null) { return 0; } if (mesh == null) { return 0; }
@ -15827,12 +15851,12 @@
if ((mesh == null) || (mesh.links == null)) { return 0; } if ((mesh == null) || (mesh.links == null)) { return 0; }
// Check if super user // Check if super user
if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return 0xFFFFFFFF; if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return removeUserRights(0xFFFFFFFF, userid);
// Check device group link permission // Check device group link permission
var rights = 0, r = mesh.links[userid]; var rights = 0, r = mesh.links[userid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here. if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a device group link, stop here.
rights = r.rights; rights = r.rights;
} }
@ -15844,14 +15868,14 @@
if (i.startsWith('ugrp/')) { if (i.startsWith('ugrp/')) {
r = mesh.links[i]; r = mesh.links[i];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here. if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a user group, stop here.
rights |= r.rights; // TODO: Deal with reverse permissions rights |= r.rights; // TODO: Deal with reverse permissions
} }
} }
} }
} }
return rights; return removeUserRights(rights, userid);
} }
// Returns true if the user can view the given device group // Returns true if the user can view the given device group
@ -15883,7 +15907,7 @@
if (userid == null) { userid = userinfo._id; } if (userid == null) { userid = userinfo._id; }
if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
var r = GetMeshRights(node.meshid, userid); var r = GetMeshRights(node.meshid, userid);
if (r == 0xFFFFFFFF) return r; if (r == 0xFFFFFFFF) return removeUserRights(r, userid);
// Check direct device rights using device data // Check direct device rights using device data
if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions
@ -15907,7 +15931,7 @@
} }
} }
*/ */
return r; return removeUserRights(r, userid);
} }
// Return true if the device is visible to the user // Return true if the device is visible to the user

View File

@ -6799,6 +6799,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Access Control Functions // Access Control Functions
// //
// Remove user rights
function removeUserRights(rights, user) {
if (user.removeRights == null) return rights;
var add = 0, substract = 0;
if ((user.removeRights & 0x00010000) != 0) { add += 0x00010000; } // No Desktop
if ((user.removeRights & 0x00000100) != 0) { add += 0x00000100; } // Desktop View Only
if ((user.removeRights & 0x00000200) != 0) { add += 0x00000200; } // No Terminal
if ((user.removeRights & 0x00000400) != 0) { add += 0x00000400; } // No Files
if ((user.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
if (rights != 0xFFFFFFFF) {
// If not administrator, add and subsctract restrictions
rights |= add;
rights &= (0xFFFFFFFF - substract);
} else {
// If administrator for a device group, start with permissions and add and subsctract restrictions
rights = 1 + 2 + 4 + 8 + 32 + 64 + 128 + 16384 + 32768 + 131072 + 262144 + 524288 + 1048576;
rights |= add;
rights &= (0xFFFFFFFF - substract);
}
return rights;
}
// Return the node and rights for a given nodeid // Return the node and rights for a given nodeid
obj.GetNodeWithRights = function (domain, user, nodeid, func) { obj.GetNodeWithRights = function (domain, user, nodeid, func) {
// Perform user pre-validation // Perform user pre-validation
@ -6818,7 +6840,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// This is a super user that can see all device groups for a given domain // This is a super user that can see all device groups for a given domain
if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (nodes[0].domain == user.domain)) { if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (nodes[0].domain == user.domain)) {
func(nodes[0], 0xFFFFFFFF, true); return; func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return;
} }
// If no links, stop here. // If no links, stop here.
@ -6827,7 +6849,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Check device link // Check device link
var rights = 0, visible = false, r = user.links[nodeid]; var rights = 0, visible = false, r = user.links[nodeid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device link, stop here. if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a device link, stop here.
rights |= r.rights; rights |= r.rights;
visible = true; visible = true;
} }
@ -6835,7 +6857,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Check device group link // Check device group link
r = user.links[nodes[0].meshid]; r = user.links[nodes[0].meshid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device group link, stop here. if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a device group link, stop here.
rights |= r.rights; rights |= r.rights;
visible = true; visible = true;
} }
@ -6847,13 +6869,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (g && (g.links != null)) { if (g && (g.links != null)) {
r = g.links[nodes[0].meshid]; r = g.links[nodes[0].meshid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a user group link, stop here. if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a user group link, stop here.
rights |= r.rights; // TODO: Deal with reverse rights rights |= r.rights; // TODO: Deal with reverse rights
visible = true; visible = true;
} }
r = g.links[nodeid]; r = g.links[nodeid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a user group direct link, stop here. if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a user group direct link, stop here.
rights |= r.rights; // TODO: Deal with reverse rights rights |= r.rights; // TODO: Deal with reverse rights
visible = true; visible = true;
} }
@ -6861,6 +6883,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
} }
} }
// Remove any user rights
rights = removeUserRights(rights, user);
// Return the rights we found // Return the rights we found
func(nodes[0], rights, visible); func(nodes[0], rights, visible);
}); });
@ -6954,7 +6979,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
} else return 0; } else return 0;
// Check if this is a super user that can see all device groups for a given domain // Check if this is a super user that can see all device groups for a given domain
if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return 0xFFFFFFFF; } if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return removeUserRights(0xFFFFFFFF, user); }
// Check direct user to device group permissions // Check direct user to device group permissions
if (user.links == null) return 0; if (user.links == null) return 0;
@ -6962,7 +6987,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
r = user.links[meshid]; r = user.links[meshid];
if (r != null) { if (r != null) {
var rights = r.rights; var rights = r.rights;
if (rights == 0xFFFFFFFF) { return rights; } // If the user has full access thru direct link, stop here. if (rights == 0xFFFFFFFF) { return removeUserRights(rights, user); } // If the user has full access thru direct link, stop here.
} }
// Check if we are part of any user groups that would give this user more access. // Check if we are part of any user groups that would give this user more access.
@ -6973,7 +6998,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
r = g.links[meshid]; r = g.links[meshid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { if (r.rights == 0xFFFFFFFF) {
return r.rights; // If the user hash full access thru a user group link, stop here. return removeUserRights(r.rights, user); // If the user hash full access thru a user group link, stop here.
} else { } else {
rights |= r.rights; // Add to existing rights (TODO: Deal with reverse rights) rights |= r.rights; // Add to existing rights (TODO: Deal with reverse rights)
} }
@ -6983,7 +7008,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
} }
} }
return rights; return removeUserRights(rights, user);
} }
// Returns true if the user can view the given device group // Returns true if the user can view the given device group
@ -7022,11 +7047,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (typeof user == 'string') { user = obj.users[user]; } if (typeof user == 'string') { user = obj.users[user]; }
if (user == null) { return 0; } if (user == null) { return 0; }
var r = obj.GetMeshRights(user, mesh); var r = obj.GetMeshRights(user, mesh);
if (r == 0xFFFFFFFF) return r; if (r == 0xFFFFFFFF) return removeUserRights(r, user);
// Check direct device rights using device data // Check direct device rights using device data
if ((user.links != null) && (user.links[nodeid] != null)) { r |= user.links[nodeid].rights; } // TODO: Deal with reverse permissions if ((user.links != null) && (user.links[nodeid] != null)) { r |= user.links[nodeid].rights; } // TODO: Deal with reverse permissions
if (r == 0xFFFFFFFF) return r; if (r == 0xFFFFFFFF) return removeUserRights(r, user);
// Check direct device rights thru a user group // Check direct device rights thru a user group
for (var i in user.links) { for (var i in user.links) {
@ -7036,7 +7061,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
} }
} }
return r; return removeUserRights(r, user);
} }
// Returns a list of displatch targets for a given mesh // Returns a list of displatch targets for a given mesh