Completed user access rights removal feature, #3065

Ylian Saint-Hilaire committed Aug 27, 2021 at 14:42 UTC 41ecece9a9f172bbafa68ded5209f372af0c3713
6 files changed +104 -30
agents/meshcore.js
+1
@@ -874,6 +874,7 @@ function handleServerCommand(data) {
874 case 'msg': {
875 switch (data.type) {
876 case 'console': { // Process a console command
877 + if ((typeof data.rights != 'number') || ((data.rights & 16) == 0)) break; // Check console rights
878 if (data.value && data.sessionid) {
879 MeshServerLogEx(17, [data.value], "Processing console command: " + data.value, data);
880 var args = splitArgs(data.value);
agents/recoverycore.js
+1
@@ -911,6 +911,7 @@ require('MeshAgent').AddCommandHandler(function (data) {
911 {
912 switch (data.type) {
913 case 'console': { // Process a console command
914 + if ((typeof data.rights != 'number') || ((data.rights & 16) == 0)) break; // Check console rights
915 if (data.value && data.sessionid) {
916 var args = splitArgs(data.value);
917 processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
meshuser.js
+2 -2
@@ -4313,7 +4313,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4313
4314 // Get the node and the rights for this node
4315 parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
4316 - if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return;
4316 + if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
4317
4318 // Ask for clipboard data from agent
4319 var agent = parent.wsagents[node._id];
@@ -4326,7 +4326,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4326
4327 // Get the node and the rights for this node
4328 parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
4329 - if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return;
4329 + if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
4330
4331 // Send clipboard data to the agent
4332 var agent = parent.wsagents[node._id];
views/default-mobile.handlebars
+32 -9
@@ -3549,7 +3549,7 @@
3549
3550 if ((currentDevicePanel != 5) &&
3551 (currentNode != null) &&
3552 - ((meshrights & 8) || (meshrights & 256)) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 65536) == 0)) &&
3552 + ((meshrights & 8) || (meshrights & 256)) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0)) &&
3553 (((currentNode.agent == null) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 2)))
3554 ) { menus.push({ n: "Terminal", f: 'setupDeviceMenu(5)' }); }
3555
@@ -6359,6 +6359,28 @@
6359 // These must match server
6360 //
6361
6362 + // Remove user rights
6363 + function removeUserRights(rights, userid) {
6364 + if ((userid != userinfo._id) || (userinfo.removeRights == null)) return rights;
6365 + var add = 0, substract = 0;
6366 + if ((userinfo.removeRights & 0x00010000) != 0) { add += 0x00010000; } // No Desktop
6367 + if ((userinfo.removeRights & 0x00000100) != 0) { add += 0x00000100; } // Desktop View Only
6368 + if ((userinfo.removeRights & 0x00000200) != 0) { add += 0x00000200; } // No Terminal
6369 + if ((userinfo.removeRights & 0x00000400) != 0) { add += 0x00000400; } // No Files
6370 + if ((userinfo.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
6371 + if (rights != 0xFFFFFFFF) {
6372 + // If not administrator, add and subsctract restrictions
6373 + rights |= add;
6374 + rights &= (0xFFFFFFFF - substract);
6375 + } else {
6376 + // If administrator for a device group, start with permissions and add and subsctract restrictions
6377 + rights = 1 + 2 + 4 + 8 + 32 + 64 + 128 + 16384 + 32768 + 131072 + 262144 + 524288 + 1048576;
6378 + rights |= add;
6379 + rights &= (0xFFFFFFFF - substract);
6380 + }
6381 + return rights;
6382 + }
6383 +
6384 // Get the right of a user on a given device group
6385 function GetMeshRights(mesh, userid) {
6386 if (mesh == null) { return 0; }
@@ -6367,12 +6389,12 @@
6389 if ((mesh == null) || (mesh.links == null)) { return 0; }
6390
6391 // Check if super user
6370 - if (userinfo.manageAllDeviceGroups && (userid == userinfo._id)) return 0xFFFFFFFF;
6392 + if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return removeUserRights(0xFFFFFFFF, userid);
6393
6394 // Check device group link permission
6395 var rights = 0, r = mesh.links[userid];
6396 if (r != null) {
6375 - if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here.
6397 + if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a device group link, stop here.
6398 rights = r.rights;
6399 }
6400
@@ -6384,14 +6406,14 @@
6406 if (i.startsWith('ugrp/')) {
6407 r = mesh.links[i];
6408 if (r != null) {
6387 - if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here.
6409 + if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a user group, stop here.
6410 rights |= r.rights; // TODO: Deal with reverse permissions
6411 }
6412 }
6413 }
6414 }
6415
6394 - return rights;
6416 + return removeUserRights(rights, userid);
6417 }
6418
6419 // Returns true if the user can view the given device group
@@ -6403,7 +6425,7 @@
6425 if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link
6426
6427 // Check if user user
6406 - if (userinfo.manageAllDeviceGroups && (userid == userinfo._id)) return true;
6428 + if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return true;
6429
6430 // Check permissions thru user groups
6431 var user = null;
@@ -6423,8 +6445,7 @@
6445 if (userid == null) { userid = userinfo._id; }
6446 if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
6447 var r = GetMeshRights(node.meshid, userid);
6426 - if (r == 0xFFFFFFFF) return r;
6427 - var user = null;
6448 + if (r == 0xFFFFFFFF) return removeUserRights(r, userid);
6449
6450 // Check direct device rights using device data
6451 if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions
@@ -6438,6 +6459,7 @@
6459
6460 // Check direct device rights using user data
6461 /*
6462 + var user = null;
6463 if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } }
6464 if ((user != null) && (user.links != null)) {
6465 var r2 = user.links[node._id];
@@ -6447,7 +6469,7 @@
6469 }
6470 }
6471 */
6450 - return r;
6472 + return removeUserRights(r, userid);
6473 }
6474
6475 // Return true if the device is visible to the user
@@ -6468,6 +6490,7 @@
6490 return false;
6491 }
6492
6493 +
6494 //
6495 // Generic Methods
6496 //
views/default.handlebars
+31 -7
@@ -2807,10 +2807,12 @@
2807 if (userinfo._id == message.event.account._id) {
2808 var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
2809 var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
2810 + var newRemoveRights = message.event.account.removeRights?message.event.account.removeRights:0;
2811 + var oldRemoveRights = userinfo.removeRights?userinfo.removeRights:0;
2812 if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
2813 var oldgroups = userinfo.groups;
2814 userinfo = message.event.account;
2813 - if ((oldsiteadmin != newsiteadmin) || (message.event.accountImageChange == 1)) { // If the site admin permission or user image has changed...
2815 + if ((oldsiteadmin != newsiteadmin) || (oldRemoveRights != newRemoveRights) || (message.event.accountImageChange == 1)) { // If the site admin permission or user image has changed...
2816 if (message.event.accountImageChange == 1) { userinfo.accountImageRnd = Math.floor(Math.random() * 9999999999); }
2817 updateSiteAdmin();
2818 }
@@ -15819,6 +15821,28 @@
15821 // These must match server
15822 //
15823
15824 + // Remove user rights
15825 + function removeUserRights(rights, userid) {
15826 + if ((userid != userinfo._id) || (userinfo.removeRights == null)) return rights;
15827 + var add = 0, substract = 0;
15828 + if ((userinfo.removeRights & 0x00010000) != 0) { add += 0x00010000; } // No Desktop
15829 + if ((userinfo.removeRights & 0x00000100) != 0) { add += 0x00000100; } // Desktop View Only
15830 + if ((userinfo.removeRights & 0x00000200) != 0) { add += 0x00000200; } // No Terminal
15831 + if ((userinfo.removeRights & 0x00000400) != 0) { add += 0x00000400; } // No Files
15832 + if ((userinfo.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
15833 + if (rights != 0xFFFFFFFF) {
15834 + // If not administrator, add and subsctract restrictions
15835 + rights |= add;
15836 + rights &= (0xFFFFFFFF - substract);
15837 + } else {
15838 + // If administrator for a device group, start with permissions and add and subsctract restrictions
15839 + rights = 1 + 2 + 4 + 8 + 32 + 64 + 128 + 16384 + 32768 + 131072 + 262144 + 524288 + 1048576;
15840 + rights |= add;
15841 + rights &= (0xFFFFFFFF - substract);
15842 + }
15843 + return rights;
15844 + }
15845 +
15846 // Get the right of a user on a given device group
15847 function GetMeshRights(mesh, userid) {
15848 if (mesh == null) { return 0; }
@@ -15827,12 +15851,12 @@
15851 if ((mesh == null) || (mesh.links == null)) { return 0; }
15852
15853 // Check if super user
15830 - if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return 0xFFFFFFFF;
15854 + if (serverinfo.manageAllDeviceGroups && (userid == userinfo._id)) return removeUserRights(0xFFFFFFFF, userid);
15855
15856 // Check device group link permission
15857 var rights = 0, r = mesh.links[userid];
15858 if (r != null) {
15835 - if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here.
15859 + if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a device group link, stop here.
15860 rights = r.rights;
15861 }
15862
@@ -15844,14 +15868,14 @@
15868 if (i.startsWith('ugrp/')) {
15869 r = mesh.links[i];
15870 if (r != null) {
15847 - if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here.
15871 + if (r.rights == 0xFFFFFFFF) { return removeUserRights(0xFFFFFFFF, userid); } // User has full rights thru a user group, stop here.
15872 rights |= r.rights; // TODO: Deal with reverse permissions
15873 }
15874 }
15875 }
15876 }
15877
15854 - return rights;
15878 + return removeUserRights(rights, userid);
15879 }
15880
15881 // Returns true if the user can view the given device group
@@ -15883,7 +15907,7 @@
15907 if (userid == null) { userid = userinfo._id; }
15908 if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
15909 var r = GetMeshRights(node.meshid, userid);
15886 - if (r == 0xFFFFFFFF) return r;
15910 + if (r == 0xFFFFFFFF) return removeUserRights(r, userid);
15911
15912 // Check direct device rights using device data
15913 if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions
@@ -15907,7 +15931,7 @@
15931 }
15932 }
15933 */
15910 - return r;
15934 + return removeUserRights(r, userid);
15935 }
15936
15937 // Return true if the device is visible to the user
webserver.js
+37 -12
@@ -6799,6 +6799,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6799 // Access Control Functions
6800 //
6801
6802 + // Remove user rights
6803 + function removeUserRights(rights, user) {
6804 + if (user.removeRights == null) return rights;
6805 + var add = 0, substract = 0;
6806 + if ((user.removeRights & 0x00010000) != 0) { add += 0x00010000; } // No Desktop
6807 + if ((user.removeRights & 0x00000100) != 0) { add += 0x00000100; } // Desktop View Only
6808 + if ((user.removeRights & 0x00000200) != 0) { add += 0x00000200; } // No Terminal
6809 + if ((user.removeRights & 0x00000400) != 0) { add += 0x00000400; } // No Files
6810 + if ((user.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
6811 + if (rights != 0xFFFFFFFF) {
6812 + // If not administrator, add and subsctract restrictions
6813 + rights |= add;
6814 + rights &= (0xFFFFFFFF - substract);
6815 + } else {
6816 + // If administrator for a device group, start with permissions and add and subsctract restrictions
6817 + rights = 1 + 2 + 4 + 8 + 32 + 64 + 128 + 16384 + 32768 + 131072 + 262144 + 524288 + 1048576;
6818 + rights |= add;
6819 + rights &= (0xFFFFFFFF - substract);
6820 + }
6821 + return rights;
6822 + }
6823 +
6824 // Return the node and rights for a given nodeid
6825 obj.GetNodeWithRights = function (domain, user, nodeid, func) {
6826 // Perform user pre-validation
@@ -6818,7 +6840,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6840
6841 // This is a super user that can see all device groups for a given domain
6842 if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (nodes[0].domain == user.domain)) {
6821 - func(nodes[0], 0xFFFFFFFF, true); return;
6843 + func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return;
6844 }
6845
6846 // If no links, stop here.
@@ -6827,7 +6849,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6849 // Check device link
6850 var rights = 0, visible = false, r = user.links[nodeid];
6851 if (r != null) {
6830 - if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device link, stop here.
6852 + if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a device link, stop here.
6853 rights |= r.rights;
6854 visible = true;
6855 }
@@ -6835,7 +6857,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6857 // Check device group link
6858 r = user.links[nodes[0].meshid];
6859 if (r != null) {
6838 - if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device group link, stop here.
6860 + if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a device group link, stop here.
6861 rights |= r.rights;
6862 visible = true;
6863 }
@@ -6847,13 +6869,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6869 if (g && (g.links != null)) {
6870 r = g.links[nodes[0].meshid];
6871 if (r != null) {
6850 - if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a user group link, stop here.
6872 + if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a user group link, stop here.
6873 rights |= r.rights; // TODO: Deal with reverse rights
6874 visible = true;
6875 }
6876 r = g.links[nodeid];
6877 if (r != null) {
6856 - if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a user group direct link, stop here.
6878 + if (r.rights == 0xFFFFFFFF) { func(nodes[0], removeUserRights(0xFFFFFFFF, user), true); return; } // User has full rights thru a user group direct link, stop here.
6879 rights |= r.rights; // TODO: Deal with reverse rights
6880 visible = true;
6881 }
@@ -6861,6 +6883,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6883 }
6884 }
6885
6886 + // Remove any user rights
6887 + rights = removeUserRights(rights, user);
6888 +
6889 // Return the rights we found
6890 func(nodes[0], rights, visible);
6891 });
@@ -6954,7 +6979,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6979 } else return 0;
6980
6981 // Check if this is a super user that can see all device groups for a given domain
6957 - if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return 0xFFFFFFFF; }
6982 + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return removeUserRights(0xFFFFFFFF, user); }
6983
6984 // Check direct user to device group permissions
6985 if (user.links == null) return 0;
@@ -6962,7 +6987,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6987 r = user.links[meshid];
6988 if (r != null) {
6989 var rights = r.rights;
6965 - if (rights == 0xFFFFFFFF) { return rights; } // If the user has full access thru direct link, stop here.
6990 + if (rights == 0xFFFFFFFF) { return removeUserRights(rights, user); } // If the user has full access thru direct link, stop here.
6991 }
6992
6993 // 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) {
6998 r = g.links[meshid];
6999 if (r != null) {
7000 if (r.rights == 0xFFFFFFFF) {
6976 - return r.rights; // If the user hash full access thru a user group link, stop here.
7001 + return removeUserRights(r.rights, user); // If the user hash full access thru a user group link, stop here.
7002 } else {
7003 rights |= r.rights; // Add to existing rights (TODO: Deal with reverse rights)
7004 }
@@ -6983,7 +7008,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
7008 }
7009 }
7010
6986 - return rights;
7011 + return removeUserRights(rights, user);
7012 }
7013
7014 // Returns true if the user can view the given device group
@@ -7022,11 +7047,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
7047 if (typeof user == 'string') { user = obj.users[user]; }
7048 if (user == null) { return 0; }
7049 var r = obj.GetMeshRights(user, mesh);
7025 - if (r == 0xFFFFFFFF) return r;
7050 + if (r == 0xFFFFFFFF) return removeUserRights(r, user);
7051
7052 // Check direct device rights using device data
7053 if ((user.links != null) && (user.links[nodeid] != null)) { r |= user.links[nodeid].rights; } // TODO: Deal with reverse permissions
7029 - if (r == 0xFFFFFFFF) return r;
7054 + if (r == 0xFFFFFFFF) return removeUserRights(r, user);
7055
7056 // Check direct device rights thru a user group
7057 for (var i in user.links) {
@@ -7036,7 +7061,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
7061 }
7062 }
7063
7039 - return r;
7064 + return removeUserRights(r, user);
7065 }
7066
7067 // Returns a list of displatch targets for a given mesh