diff --git a/apprelays.js b/apprelays.js
index cd6bc5fad5..8a0ee63950 100644
--- a/apprelays.js
+++ b/apprelays.js
@@ -57,6 +57,7 @@ const MESHRIGHT_RESETOFF = 0x00040000; // 262144
const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
const MESHRIGHT_RELAY = 0x00200000; // 2097152
+const MESHRIGHT_HIDERDPSESSIONS = 0x00400000; // 4194304
const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// SerialTunnel object is used to embed TLS within another connection.
diff --git a/meshagent.js b/meshagent.js
index 7169b9ffa9..27da4ea719 100644
--- a/meshagent.js
+++ b/meshagent.js
@@ -1214,6 +1214,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
obj.consoleKickValue = command.value;
}
}
+ else if (command.type == 'userSessions') {
+ const rights = parent.GetNodeRights(parent.wssessions2[command.sessionid].userid, obj.dbMeshKey, obj.dbNodeKey);
+ if ((rights !== 0xFFFFFFFF) && (rights & 0x00400000)) {
+ command.data = Object.fromEntries(Object.entries(command.data).filter(([k,v]) => (!v.StationName.toUpperCase().startsWith('RDP-'))));
+ console.log(rights.toString(16).padStart(8,'0'), command);
+ }
+ }
// Route a message
parent.routeAgentCommand(command, obj.domain.id, obj.dbNodeKey, obj.dbMeshKey);
diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json
index 91cec3b8c3..d733c22402 100644
--- a/meshcentral-config-schema.json
+++ b/meshcentral-config-schema.json
@@ -1522,6 +1522,11 @@
]
}
},
+ "applyFeaturePermissionsToRouterAndWebTools": {
+ "type": "boolean",
+ "default": true,
+ "description": "Hides RDP, SSH or SCP links if access to Desktop, Terminal or Files is denied."
+ },
"deviceMeshRouterLinks": {
"type": "object",
"properties": {
@@ -1929,6 +1934,15 @@
"default": true,
"description": "When enabled, activates the built-in web-based VNC client."
},
+ "novncargs": {
+ "type": "string",
+ "default": "show_dot=1",
+ "description": "Additional arguments for nVNC. URL-encoded and sparated by ampersand (&)."
+ },
+ "novncViewOnlyPort": {
+ "type": ["number", "array"],
+ "description": "TCP port where a VNC server is listening in view-only mode. Single number or array in Object.fromEntries()-compatible format."
+ },
"mstsc": {
"type": "boolean",
"default": true,
@@ -2324,7 +2338,7 @@
"viewonly": {
"type": "boolean",
"description": "When set to true, the remote desktop feature is view only.",
- "default": "false"
+ "default": false
}
}
},
diff --git a/meshcentral.js b/meshcentral.js
index a792dda56f..9493c8b77f 100644
--- a/meshcentral.js
+++ b/meshcentral.js
@@ -3216,6 +3216,8 @@ function CreateMeshCentralServer(config, args) {
// Sign windows agents
obj.signMeshAgents = function (domain, func) {
+ // Skip signing to speed up debugging
+ if ('MESHCENTRAL_DEV_NO_AGENT_SIGNING' in process.env && (()=> { try { return require('node:inspector').url() !== undefined; } catch (_) { return false; } }).call()) { return void func(); }
// Setup the domain is specified
var objx = domain, suffix = '';
if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
diff --git a/meshipkvm.js b/meshipkvm.js
index 2623eb9040..d6e2879ea6 100644
--- a/meshipkvm.js
+++ b/meshipkvm.js
@@ -34,6 +34,8 @@ function CreateIPKVMManager(parent) {
const MESHRIGHT_RESETOFF = 0x00040000; // 262144
const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
const MESHRIGHT_DEVICEDETAILS = 0x00100000; // ?1048576?
+ const MESHRIGHT_RELAY = 0x00200000; // 2097152
+ const MESHRIGHT_HIDERDPSESSIONS = 0x00400000; // 4194304
const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// Subscribe for mesh creation events
diff --git a/meshrelay.js b/meshrelay.js
index 7f91904df8..bf58046821 100644
--- a/meshrelay.js
+++ b/meshrelay.js
@@ -36,6 +36,7 @@ const MESHRIGHT_RESETOFF = 0x00040000; // 262144
const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
const MESHRIGHT_RELAY = 0x00200000; // 2097152
+const MESHRIGHT_HIDERDPSESSIONS = 0x00400000; // 4194304
const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// Protocol:
@@ -874,14 +875,31 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
parent.db.Get(cookie.nodeid, function (err, docs) {
if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
const node = docs[0];
+ const rights = parent.GetNodeRights(obj.user, node.meshid, node._id);
// 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; }
+ if ((obj.nouser !== true) && ((rights & 0x00200008) == 0)) { console.log('ERR: Access denied (1)'); try { obj.close(); } catch (ex) { } return; }
// Set nodeid and meshid
obj.nodeid = node._id;
obj.meshid = node.meshid;
+ function getNoVncViewOnlyPort(rfbport = 5900) {
+ let novncvop = domain.novncviewonlyport;
+ if (typeof novncvop === 'number') { return novncvop; }
+ if (Array.isArray(novncvop)) { novncvop = domain.novncviewonlyport = Object.fromEntries(novncvop); }
+ const tokens = [obj.meshid, `mesh/${domain.id}/${parent.meshes[obj.meshid].name}`, obj.nodeid, `node/${domain.id}/${node.name}`, '*'];
+ tokens.some((val) => ((val = +novncvop[val]) ? ((rfbport = val), true) : false));
+ return rfbport;
+ }
+ if (domain.applyfeaturepermissionstorouterandwebtools !== false) {
+ switch (cookie.tcpport) {
+ // don't know why, but we have to terminate() the websocket to close the connection. or is a feature to avoid DoS?
+ case node.rdpport ?? 3389: { if ((rights !== 0xFFFFFFFF) && (rights & MESHRIGHT_REMOTEVIEWONLY)) { console.log('ERR: Access denied (1)'); try { obj.close(); /*ws.terminate();*/ } catch (ex) { } return; } break; }
+ case node.rfbport ?? 5900: { if ((rights !== 0xFFFFFFFF) && (rights & MESHRIGHT_REMOTEVIEWONLY)) { cookie.tcpport = getNoVncViewOnlyPort(node.rfbport); } break; }
+ }
+ }
+
// Send connection request to agent
const rcookieData = {};
if (user != null) { rcookieData.ruserid = user._id; } else if (obj.nouser === true) { rcookieData.nouser = 1; }
diff --git a/meshuser.js b/meshuser.js
index ac237dfdf6..ca5a55bb51 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -53,6 +53,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
const MESHRIGHT_GUESTSHARING = 0x00080000; // 524288
const MESHRIGHT_DEVICEDETAILS = 0x00100000; // 1048576
const MESHRIGHT_RELAY = 0x00200000; // 2097152
+ const MESHRIGHT_HIDERDPSESSIONS = 0x00400000; // 4194304
const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// Site rights
@@ -547,7 +548,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Build server information object
const allFeatures = parent.getDomainUserFeatures(domain, user, req);
- var serverinfo = { domain: domain.id, name: domain.dns ? domain.dns : parent.certificates.CommonName, mpsname: parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: args.mpspass, port: httpport, emailcheck: ((domain.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (args.lanonly != true) && (parent.certificates.CommonName != null) && (parent.certificates.CommonName.indexOf('.') != -1) && (user._id.split('/')[2].startsWith('~') == false)), domainauth: (domain.auth == 'sspi'), serverTime: Date.now(), features: allFeatures.features, features2: allFeatures.features2 };
+ var serverinfo = { domain: domain.id, name: domain.dns ? domain.dns : parent.certificates.CommonName, mpsname: parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: args.mpspass, port: httpport, emailcheck: ((domain.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (args.lanonly != true) && (parent.certificates.CommonName != null) && (parent.certificates.CommonName.indexOf('.') != -1) && (user._id.split('/')[2].startsWith('~') == false)), domainauth: (domain.auth == 'sspi'), serverTime: Date.now(), features: allFeatures.features, features2: allFeatures.features2, features3: allFeatures.features3 };
serverinfo.languages = parent.renderLanguages;
serverinfo.tlshash = Buffer.from(parent.webCertificateFullHashs[domain.id], 'binary').toString('hex').toUpperCase(); // SHA384 of server HTTPS certificate
serverinfo.agentCertHash = parent.agentCertificateHashBase64;
@@ -4722,7 +4723,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
} else {
try {
parent.parent.pluginHandler.plugins[command.plugin].serveraction(command, obj, parent);
- } catch (ex) { console.log('Error loading plugin handler (' + ex + ')'); }
+ } catch (ex) { console.log('Error executing plugin serveraction (' + ex + ')', ex.stack); }
}
break;
}
@@ -6411,6 +6412,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
if ((node == null) || ((rights & MESHRIGHT_REMOTECONTROL) == 0) || (visible == false)) return; // Access denied.
+ const applyfeaturepermissions = obj.domain.applyfeaturepermissionstorouterandwebtools !== false;
+ switch (command.tag) {
+ case 'novnc': {
+ let novncargs = domain.novncargs ?? 'show_dot=1';
+ if (applyfeaturepermissions) { novncargs += '&view_only=' +!!(rights & MESHRIGHT_REMOTEVIEWONLY); }
+ command.qsappend = novncargs.charAt(0) === '&' ? novncargs.slice(1) : novncargs;
+ break;
+ }
+ case 'mstsc': { if (applyfeaturepermissions && (rights & MESHRIGHT_REMOTEVIEWONLY)) { return; } break; }
+ case 'ssh': { if (applyfeaturepermissions && (rights & MESHRIGHT_NOTERMINAL)) { return; }; break; }
+ }
+
// Add a user authentication cookie to a url
var cookieContent = { userid: user._id, domainid: user.domain };
if (command.nodeid) { cookieContent.nodeid = command.nodeid; }
diff --git a/sample-config-advanced.json b/sample-config-advanced.json
index 3b7836f030..1b54e0461b 100644
--- a/sample-config-advanced.json
+++ b/sample-config-advanced.json
@@ -581,6 +581,17 @@
"_footer": "Test",
"_certUrl": "https://192.168.2.106:443/"
},
+ "_domain_with_novncViewOnlyPort": {
+ "_novnc": true,
+ "_1_novncViewOnlyPort": 5901,
+ "_2_novncViewOnlyPort": [
+ ["#_node//Oqj4ExG@mcz9ZmXMuy7YncqEKuVA1rD5o8ZUWQ8F$mA$33zwfXz$XQ5mrUYdJbss", 5901],
+ ["#_node//my-dev-box", 5902],
+ ["#_mesh//KbvW2V18kiZSNQ5zkT8Qk2s7aADf0MwS1cXUlc$WzqwbwEVYMTopJFR1uxxZzE79", 5903],
+ ["#_mesh//playground--connect", 5904],
+ ["*", 5905]
+ ]
+ },
"_info": {
"_share": "C:\\ExtraWebSite"
}
diff --git a/views/default.handlebars b/views/default.handlebars
index 8b11665a77..aa4b48006a 100644
--- a/views/default.handlebars
+++ b/views/default.handlebars
@@ -1550,6 +1550,7 @@
var debugLevel = parseInt('{{{debuglevel}}}');
var features = parseInt('{{{features}}}');
var features2 = parseInt('{{{features2}}}');
+ var features3 = parseInt('{{{features3}}}');
var sessionTime = parseInt('{{{sessiontime}}}');
var webRelayPort = parseInt('{{{webRelayPort}}}');
var webRelayDns = '{{{webRelayDns}}}';
@@ -2356,6 +2357,7 @@
if (updateNaggleFlags & 16384) { updateUsers(); }
if (updateNaggleFlags & 32768) { updateRecordings(); }
if (updateNaggleFlags & 65536) { updateLoginTokens(); }
+ if (currentNode && (updateNaggleFlags & 131072)) { updateDesktopButtons(); }
updateNaggleTimer = null;
updateNaggleFlags = 0;
gotoStartViewPage();
@@ -3006,18 +3008,18 @@
//console.log(url);
downloadFile(url, '');
} else if (message.tag == 'novnc') {
- var vncurl = window.location.origin + domainUrl + 'novnc/vnc.html?ws=wss%3A%2F%2F' + window.location.host + encodeURIComponentEx(domainUrl) + (message.localRelay?'local':'mesh') + 'relay.ashx%3Fauth%3D' + message.cookie + '&show_dot=1' + (urlargs.key?('&key=' + urlargs.key):'') + '&l={{{lang}}}';
+ var vncurl = window.location.origin + domainUrl + 'novnc/vnc.html?ws=wss%3A%2F%2F' + window.location.host + encodeURIComponentEx(domainUrl) + (message.localRelay ? 'local' : 'mesh') + 'relay.ashx%3Fauth%3D' + message.cookie + (urlargs.key?('&key=' + urlargs.key):'') + '&l={{{lang}}}' + (message.qsappend ? '&' + message.qsappend : '');
var node = getNodeFromId(message.nodeid);
if (node != null) { vncurl += '&name=' + encodeURIComponentEx(node.name); }
safeNewWindow(vncurl, 'mcnovnc/' + message.nodeid);
} else if (message.tag == 'mstsc') {
- var rdpurl = window.location.origin + domainUrl + 'mstsc.html?ws=' + message.cookie + (urlargs.key?('&key=' + urlargs.key):'');
+ var rdpurl = window.location.origin + domainUrl + 'mstsc.html?ws=' + message.cookie + (urlargs.key ? ('&key=' + urlargs.key) : '') + (message.qsappend ? '&' + message.qsappend : '');
var node = getNodeFromId(message.nodeid);
if (node != null) { rdpurl += '&name=' + encodeURIComponentEx(node.name); }
if (message.localRelay) { rdpurl += '&local=1'; }
safeNewWindow(rdpurl, 'mcmstsc/' + message.nodeid);
} else if (message.tag == 'ssh') {
- var sshurl = window.location.origin + domainUrl + 'ssh.html?ws=' + message.cookie + (urlargs.key?('&key=' + urlargs.key):'');
+ var sshurl = window.location.origin + domainUrl + 'ssh.html?ws=' + message.cookie + (urlargs.key ? ('&key=' + urlargs.key) : '') + (message.qsappend ? '&' + message.qsappend : '');
var node = getNodeFromId(message.nodeid);
if (node != null) { sshurl += '&name=' + encodeURIComponentEx(node.name); }
if (message.localRelay) { sshurl += '&local=1'; }
@@ -3463,6 +3465,7 @@
// If we are looking at a node that is no longer visible, move back to "My Devices"
if ((xxcurrentView >= 10) && (xxcurrentView < 20) && currentNode && !IsNodeViewable(currentNode)) { setDialogMode(0); go(1); }
}
+ mainUpdate(131072);
}
mainUpdate(4 + 128 + 8192 + 16384);
if (currentNode && !IsNodeViewable(currentNode)) { currentNode = null; if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } }
@@ -6515,12 +6518,12 @@
QV('cxfiles', (node.mtype != 4) && ((node.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (rights & 8) && fileAccess);
QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (rights & 8));
QV('cxdetails', node.mtype < 3);
- QV('cxwebvnc', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0) && ((features & 0x20000000) == 0)));
- QV('cxwebrdp', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0) && ((features & 0x40000000) == 0)));
- QV('cxwebssh', ((features2 & 0x200) && (((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0)));
+ QV('cxwebvnc', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 65536 : 0))) == 8)) && ((features & 0x20000000) == 0)));
+ QV('cxwebrdp', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8)) && ((features & 0x40000000) == 0)));
+ QV('cxwebssh', ((features2 & 0x200) && (((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 512 : 0))) == 8))));
QV('cxconsole', (consoleRights && (node.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (rights & 8));
QV('cxrdp', false); // always have the RDP hidden
- if ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0)) {
+ if ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8))) {
if ((node.agent.id > 0) && (node.agent.id < 5)) {
if (navigator.platform.toLowerCase() == 'win32') {
if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.rdp != false)) {
@@ -7829,19 +7832,19 @@
}
if ((node.agent.id > 0) && (node.agent.id < 5)) {
if (navigator.platform.toLowerCase() == 'win32') {
- if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.rdp != false)) {
+ if (((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8)) && ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.rdp != false))) {
x += '' + "RDP" + ((node.rdpport && (node.rdpport != 3389)) ? '/' + node.rdpport : '') + ' ';
}
}
}
if (node.agent.id > 4) {
- if ((navigator.platform.toLowerCase() == 'win32') || (navigator.platform.toLowerCase() == 'macintel')) {
+ if (((meshrights == 0xFFFFFFFF) || ((meshrights & ( 8 | (features3 & 0x00000001 ? 512 : 0))) == 8)) && ((navigator.platform.toLowerCase() == 'win32') || (navigator.platform.toLowerCase() == 'macintel'))) {
if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.ssh != false)) {
x += '' + "SSH" + ((node.sshport && (node.sshport != 22)) ? '/' + node.sshport : '') + ' ';
}
}
if (navigator.platform.toLowerCase() == 'win32') {
- if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.scp != false)) {
+ if (((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 1024 : 0))) == 8)) && ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.scp != false))) {
x += '' + "SCP" + ((node.sshport && (node.sshport != 22)) ? '/' + node.sshport : '') + ' ';
}
}
@@ -7861,17 +7864,17 @@
}
// noVNC link
- if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights & 8) != 0) && ((features & 0x20000000) == 0)) {
+ if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 65536 : 0))) == 8 )) && ((features & 0x20000000) == 0)) {
x += '' + "Web-VNC" + ' ';
}
// MSTSC.js link
- if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights & 8) != 0) && ((features & 0x40000000) == 0)) {
+ if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8)) && ((features & 0x40000000) == 0)) {
x += '' + "Web-RDP" + ' ';
}
// SSH link
- if ((features2 & 0x200) && (((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights & 8) != 0)) {
+ if ((features2 & 0x200) && (((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 512 : 0))) == 8))) {
x += '' + "Web-SSH" + ' ';
}
@@ -8184,6 +8187,7 @@
if (rights & 512) str1.push("No Terminal");
if (rights & 1024) str1.push("No Files");
if (rights & 2048) str1.push("No AMT");
+ if (rights & 4194304) str1.push("Hide RDP");
if (rights & 4096) str1.push("Limited Input");
if (rights & 65536) str1.push("No Desktop");
if ((rights & 524288) && (serverinfo.guestdevicesharing !== false)) str1.push("Guest Share");
@@ -8218,6 +8222,7 @@
if (rights & 1024) str1.push("No Files");
if (rights & 2048) str1.push("No AMT");
if (rights & 4096) str1.push("Limited Input");
+ if (rights & 4194304) str1.push("Hide RDP");
if (rights & 65536) str1.push("No Desktop");
if ((rights & 524288) && (serverinfo.guestdevicesharing !== false)) str1.push("Guest Share");
if (str1.length > 0) { str.push('Control (' + str1.join(', ') + ')'); } else { str.push("Control"); }
@@ -9186,7 +9191,7 @@
// Show the right buttons
QV('disconnectbutton1span', (deskState != 0));
QV('connectbutton1span', (deskState == 0) && ((rights & 8) || (rights & 256)) && (currentNode.agent != null) && (currentNode.agent.caps & 1));
- QV('connectbutton1rspan', ((features & 0x40000000) == 0) && (deskState == 0) && (rights & 8) && (currentNode.agent != null) && ((currentNode.agent.id == 3) || (currentNode.agent.id == 4)));
+ QV('connectbutton1rspan', ((features & 0x40000000) == 0) && (deskState == 0) && ((rights == 0XFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 256 : 0))) == 8)) && (currentNode.agent != null) && ((currentNode.agent.id == 3) || (currentNode.agent.id == 4)));
if (mtype == 1) {
QV('connectbutton1hspan',
(deskState == 0) &&
@@ -14196,6 +14201,7 @@
x += '
';
x += '
';
x += '
';
+ x += '
';
if (serverinfo.guestdevicesharing !== false) { x += '
'; }
x += '
';
x += '
';
@@ -14277,6 +14283,7 @@
if (urights & 1024) { Q('p20nofiles').checked = true; }
if (urights & 2048) { Q('p20noamt').checked = true; }
if (urights & 4096) { Q('p20remotelimitedinput').checked = true; }
+ if (urights & 4194304) { Q('p20hiderdpsessions').checked = true; }
}
if (urights & 16) { Q('p20meshagentconsole').checked = true; }
if (urights & 32) { Q('p20meshserverfiles').checked = true; }
@@ -14330,6 +14337,7 @@
Q('p20nofiles').checked = ((devrights & 1024) != 0);
Q('p20noamt').checked = ((devrights & 2048) != 0);
Q('p20remotelimitedinput').checked = ((devrights & 4096) != 0);
+ Q('p20hiderdpsessions').checked = ((devrights & 4194304) != 0);
Q('p20limitevents').checked = ((devrights & 8192) != 0);
Q('p20chatnotify').checked = ((devrights & 16384) != 0);
Q('p20uninstall').checked = ((devrights & 32768) != 0);
@@ -14411,6 +14419,7 @@
QE('p20remoteview', nc && Q('p20remotecontrol').checked);
if (serverinfo.guestdevicesharing !== false) { QE('p20guestshare', nc && Q('p20remotecontrol').checked && (Q('p20remoteview').checked || !Q('p20remotelimitedinput').checked)); }
QE('p20remotelimitedinput', nc && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
+ QE('p20hiderdpsessions', nc && Q('p20remotecontrol').checked);
QE('p20nodesktop', nc && Q('p20remotecontrol').checked);
QE('p20noterminal', nc && Q('p20remotecontrol').checked);
QE('p20nofiles', nc && Q('p20remotecontrol').checked);
@@ -14443,6 +14452,7 @@
if (Q('p20nofiles').checked == true) meshadmin += 1024;
if (Q('p20noamt').checked == true) meshadmin += 2048;
if ((Q('p20remotelimitedinput').checked == true) && (!Q('p20remoteview').checked)) meshadmin += 4096;
+ if ((Q('p20hiderdpsessions').checked == true)) meshadmin += 4194304;
if (Q('p20limitevents').checked == true) meshadmin += 8192;
if (Q('p20chatnotify').checked == true) meshadmin += 16384;
if (Q('p20uninstall').checked == true) meshadmin += 32768;
@@ -14455,13 +14465,14 @@
// Clean up incorrect rights. If Remote Control is not selected, remove flags that don't make sense.
if ((meshadmin & 8) == 0) {
- // Remove 256, 512, 1024, 2048, 4096, 65536
+ // Remove 256, 512, 1024, 2048, 4096, 65536, 4194304
if (meshadmin & 256) { meshadmin -= 256; }
if (meshadmin & 512) { meshadmin -= 512; }
if (meshadmin & 1024) { meshadmin -= 1024; }
if (meshadmin & 2048) { meshadmin -= 2048; }
if (meshadmin & 4096) { meshadmin -= 4096; }
if (meshadmin & 65536) { meshadmin -= 65536; }
+ if (meshadmin & 4194304) { meshadmin -= 4194304; }
}
// Send the action to the server
@@ -14524,11 +14535,13 @@
if ((meshrights & 64) != 0) r.push("Wake Devices");
if ((meshrights & 128) != 0) r.push("Edit Notes");
if (((meshrights & 8) != 0) && (meshrights & 256) != 0) r.push("Remote View Only");
+ if (((meshrights & 8) != 0) && (meshrights & 4194304) != 0) r.push("Hide RDP Sessionss");
if (((meshrights & 8) != 0) && (meshrights & 65536) != 0) r.push("No Desktop");
if (((meshrights & 8) != 0) && (meshrights & 512) != 0) r.push("No Terminal");
if (((meshrights & 8) != 0) && (meshrights & 1024) != 0) r.push("No Files");
if (((meshrights & 8) != 0) && (meshrights & 2048) != 0) r.push("No Intel® AMT");
if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Limited Input");
+ if (((meshrights & 8) != 0) && ((meshrights & 4194304) != 0) && ((meshrights & 256) == 0)) r.push("Hide RDP");
if ((meshrights & 8192) != 0) r.push("Self Events Only");
if ((meshrights & 16384) != 0) r.push("Chat & Notify");
if ((meshrights & 32768) != 0) r.push("Uninstall");
@@ -16459,8 +16472,8 @@
var cr = 0, mesh = omeshes[i], r = currentUserGroup.links[mesh._id].rights, trash = '', rights = makeDeviceGroupRightsString(r);
if ((userinfo.links) && (userinfo.links[mesh._id] != null) && (userinfo.links[mesh._id].rights != null)) { cr = userinfo.links[mesh._id].rights; }
var meshname = '' + "Unknown Device Group" + '';
- if (mesh) { meshname = '' + mesh.name + ''; } else {}
- if ((cr & 2) != 0) {
+ if (mesh) { meshname = '' + mesh.name + ''; } else { }
+ if ((userinfo.siteadmin == 0xFFFFFFFF) || ((cr & 2) != 0)) {
trash = '
';
rights = '' + rights + '
';
}
@@ -16760,8 +16773,11 @@
if ((serverinfo.usersSessionRecording == 1) && (user.flags) && (user.flags & 2)) { userFeatures.push("Record Sessions"); }
if (user.removeRights) {
if ((user.removeRights & 0x00000008) != 0) { userFeatures.push("No Remote Control"); } else {
- if ((user.removeRights & 0x00010000) != 0) { userFeatures.push("No Desktop"); }
- else if ((user.removeRights & 0x00000100) != 0) { userFeatures.push("Desktop View Only"); }
+ if ((user.removeRights & 0x00010000) != 0) { userFeatures.push("No Desktop"); } else {
+ if ((user.removeRights & 0x00000100) != 0) { userFeatures.push("Desktop View Only"); }
+ else if ((user.removeRights & 0x00001000) != 0) { userFeatures.push("Limited Input"); }
+ if ((user.removeRights & 0x00400000) != 0) { userFeatures.push("Hide RDP"); }
+ }
if ((user.removeRights & 0x00000200) != 0) { userFeatures.push("No Terminal"); }
if ((user.removeRights & 0x00000400) != 0) { userFeatures.push("No Files"); }
}
@@ -16986,6 +17002,8 @@
x += '
';
}
@@ -19002,6 +19026,8 @@
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 & 0x00001000) != 0) { add += 0x00001000; } // Limited Input Only
+ if ((userinfo.removeRights & 0x00400000) != 0) { add += 0x00400000; } // Hide RDP Sessions
if ((userinfo.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
if ((userinfo.removeRights & 0x00008000) != 0) { substract += 0x00008000; } // No Uninstall
if ((userinfo.removeRights & 0x00020000) != 0) { substract += 0x00020000; } // No Remote Command
diff --git a/views/default3.handlebars b/views/default3.handlebars
index b3cd7ba78b..2404a5164e 100644
--- a/views/default3.handlebars
+++ b/views/default3.handlebars
@@ -1977,6 +1977,7 @@
var debugLevel = parseInt('{{{debuglevel}}}');
var features = parseInt('{{{features}}}');
var features2 = parseInt('{{{features2}}}');
+ var features3 = parseInt('{{{features3}}}');
var sessionTime = parseInt('{{{sessiontime}}}');
var webRelayPort = parseInt('{{{webRelayPort}}}');
var webRelayDns = '{{{webRelayDns}}}';
@@ -2806,6 +2807,7 @@
if (updateNaggleFlags & 16384) { updateUsers(); }
if (updateNaggleFlags & 32768) { updateRecordings(); }
if (updateNaggleFlags & 65536) { updateLoginTokens(); }
+ if (currentNode && (updateNaggleFlags & 131072)) { updateDesktopButtons(); }
updateNaggleTimer = null;
updateNaggleFlags = 0;
gotoStartViewPage();
@@ -3461,18 +3463,18 @@
//console.log(url);
downloadFile(url, '');
} else if (message.tag == 'novnc') {
- var vncurl = window.location.origin + domainUrl + 'novnc/vnc.html?ws=wss%3A%2F%2F' + window.location.host + encodeURIComponentEx(domainUrl) + (message.localRelay ? 'local' : 'mesh') + 'relay.ashx%3Fauth%3D' + message.cookie + '&show_dot=1' + (urlargs.key ? ('&key=' + urlargs.key) : '') + '&l={{{lang}}}';
+ var vncurl = window.location.origin + domainUrl + 'novnc/vnc.html?ws=wss%3A%2F%2F' + window.location.host + encodeURIComponentEx(domainUrl) + (message.localRelay ? 'local' : 'mesh') + 'relay.ashx%3Fauth%3D' + message.cookie + (urlargs.key?('&key=' + urlargs.key):'') + '&l={{{lang}}}' + (message.qsappend ? '&' + message.qsappend : '');
var node = getNodeFromId(message.nodeid);
if (node != null) { vncurl += '&name=' + encodeURIComponentEx(node.name); }
safeNewWindow(vncurl, 'mcnovnc/' + message.nodeid);
} else if (message.tag == 'mstsc') {
- var rdpurl = window.location.origin + domainUrl + 'mstsc.html?ws=' + message.cookie + (urlargs.key ? ('&key=' + urlargs.key) : '');
+ var rdpurl = window.location.origin + domainUrl + 'mstsc.html?ws=' + message.cookie + (urlargs.key ? ('&key=' + urlargs.key) : '') + (message.qsappend ? '&' + message.qsappend : '');
var node = getNodeFromId(message.nodeid);
if (node != null) { rdpurl += '&name=' + encodeURIComponentEx(node.name); }
if (message.localRelay) { rdpurl += '&local=1'; }
safeNewWindow(rdpurl, 'mcmstsc/' + message.nodeid);
} else if (message.tag == 'ssh') {
- var sshurl = window.location.origin + domainUrl + 'ssh.html?ws=' + message.cookie + (urlargs.key ? ('&key=' + urlargs.key) : '');
+ var sshurl = window.location.origin + domainUrl + 'ssh.html?ws=' + message.cookie + (urlargs.key ? ('&key=' + urlargs.key) : '') + (message.qsappend ? '&' + message.qsappend : '');
var node = getNodeFromId(message.nodeid);
if (node != null) { sshurl += '&name=' + encodeURIComponentEx(node.name); }
if (message.localRelay) { sshurl += '&local=1'; }
@@ -3925,6 +3927,7 @@
// If we are looking at a node that is no longer visible, move back to "My Devices"
if ((xxcurrentView >= 10) && (xxcurrentView < 20) && currentNode && !IsNodeViewable(currentNode)) { setDialogMode(0); go(1); }
}
+ mainUpdate(131072);
}
mainUpdate(4 + 128 + 8192 + 16384);
if (currentNode && !IsNodeViewable(currentNode)) { currentNode = null; if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } }
@@ -7173,12 +7176,12 @@
QV('cxfiles', (node.mtype != 4) && ((node.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (rights & 8) && fileAccess);
QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (rights & 8));
QV('cxdetails', node.mtype < 3);
- QV('cxwebvnc', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0) && ((features & 0x20000000) == 0)));
- QV('cxwebrdp', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0) && ((features & 0x40000000) == 0)));
- QV('cxwebssh', ((features2 & 0x200) && (((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0)));
+ QV('cxwebvnc', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 65536 : 0))) == 8)) && ((features & 0x20000000) == 0)));
+ QV('cxwebrdp', ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8)) && ((features & 0x40000000) == 0)));
+ QV('cxwebssh', ((features2 & 0x200) && (((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 512 : 0))) == 8))));
QV('cxconsole', (consoleRights && (node.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (rights & 8));
QV('cxrdp', false); // always have the RDP hidden
- if ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights & 8) != 0)) {
+ if ((((node.conn & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((rights == 0xFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8))) {
if ((node.agent.id > 0) && (node.agent.id < 5)) {
if (navigator.platform.toLowerCase() == 'win32') {
if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.rdp != false)) {
@@ -8497,19 +8500,19 @@
}
if ((node.agent.id > 0) && (node.agent.id < 5)) {
if (navigator.platform.toLowerCase() == 'win32') {
- if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.rdp != false)) {
+ if (((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8)) && ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.rdp != false))) {
x += '' + "RDP" + ((node.rdpport && (node.rdpport != 3389)) ? '/' + node.rdpport : '') + ' ';
}
}
}
if (node.agent.id > 4) {
- if ((navigator.platform.toLowerCase() == 'win32') || (navigator.platform.toLowerCase() == 'macintel')) {
+ if (((meshrights == 0xFFFFFFFF) || ((meshrights & ( 8 | (features3 & 0x00000001 ? 512 : 0))) == 8)) && ((navigator.platform.toLowerCase() == 'win32') || (navigator.platform.toLowerCase() == 'macintel'))) {
if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.ssh != false)) {
x += '' + "SSH" + ((node.sshport && (node.sshport != 22)) ? '/' + node.sshport : '') + ' ';
}
}
if (navigator.platform.toLowerCase() == 'win32') {
- if ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.scp != false)) {
+ if (((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 1024 : 0))) == 8)) && ((serverinfo.devicemeshrouterlinks == null) || (serverinfo.devicemeshrouterlinks.scp != false))) {
x += '' + "SCP" + ((node.sshport && (node.sshport != 22)) ? '/' + node.sshport : '') + ' ';
}
}
@@ -8529,17 +8532,17 @@
}
// noVNC link
- if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights & 8) != 0) && ((features & 0x20000000) == 0)) {
+ if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 65536 : 0))) == 8 )) && ((features & 0x20000000) == 0)) {
x += '' + "Web-VNC" + ' ';
}
// MSTSC.js link
- if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights & 8) != 0) && ((features & 0x40000000) == 0)) {
+ if ((((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 256 | 65536 : 0))) == 8)) && ((features & 0x40000000) == 0)) {
x += '' + "Web-RDP" + ' ';
}
// SSH link
- if ((features2 & 0x200) && (((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights & 8) != 0)) {
+ if ((features2 & 0x200) && (((connectivity & 1) != 0) || (node.mtype == 3)) && (node.agent) && ((meshrights == 0xFFFFFFFF) || ((meshrights & (8 | (features3 & 0x00000001 ? 512 : 0))) == 8))) {
x += '' + "Web-SSH" + ' ';
}
@@ -8857,6 +8860,7 @@
if (rights & 512) str1.push("No Terminal");
if (rights & 1024) str1.push("No Files");
if (rights & 2048) str1.push("No AMT");
+ if (rights & 4194304) str1.push("Hide RDP");
if (rights & 4096) str1.push("Limited Input");
if (rights & 65536) str1.push("No Desktop");
if ((rights & 524288) && (serverinfo.guestdevicesharing !== false)) str1.push("Guest Share");
@@ -8891,6 +8895,7 @@
if (rights & 1024) str1.push("No Files");
if (rights & 2048) str1.push("No AMT");
if (rights & 4096) str1.push("Limited Input");
+ if (rights & 4194304) str1.push("Hide RDP");
if (rights & 65536) str1.push("No Desktop");
if ((rights & 524288) && (serverinfo.guestdevicesharing !== false)) str1.push("Guest Share");
if (str1.length > 0) { str.push('Control (' + str1.join(', ') + ')'); } else { str.push("Control"); }
@@ -9945,7 +9950,7 @@
// Show the right buttons
QV('disconnectbutton1span', (deskState != 0));
QV('connectbutton1span', (deskState == 0) && ((rights & 8) || (rights & 256)) && (currentNode.agent != null) && (currentNode.agent.caps & 1));
- QV('connectbutton1rspan', ((features & 0x40000000) == 0) && (deskState == 0) && (rights & 8) && (currentNode.agent != null) && ((currentNode.agent.id == 3) || (currentNode.agent.id == 4)));
+ QV('connectbutton1rspan', ((features & 0x40000000) == 0) && (deskState == 0) && ((rights == 0XFFFFFFFF) || ((rights & (8 | (features3 & 0x00000001 ? 256 : 0))) == 8)) && (currentNode.agent != null) && ((currentNode.agent.id == 3) || (currentNode.agent.id == 4)));
if (mtype == 1) {
QV('connectbutton1hspan',
(deskState == 0) &&
@@ -15272,6 +15277,7 @@
x += '
';
}
@@ -17988,8 +18001,11 @@
if ((serverinfo.usersSessionRecording == 1) && (user.flags) && (user.flags & 2)) { userFeatures.push("Record Sessions"); }
if (user.removeRights) {
if ((user.removeRights & 0x00000008) != 0) { userFeatures.push("No Remote Control"); } else {
- if ((user.removeRights & 0x00010000) != 0) { userFeatures.push("No Desktop"); }
- else if ((user.removeRights & 0x00000100) != 0) { userFeatures.push("Desktop View Only"); }
+ if ((user.removeRights & 0x00010000) != 0) { userFeatures.push("No Desktop"); } else {
+ if ((user.removeRights & 0x00000100) != 0) { userFeatures.push("Desktop View Only"); }
+ else if ((user.removeRights & 0x00001000) != 0) { userFeatures.push("Limited Input"); }
+ if ((user.removeRights & 0x00400000) != 0) { userFeatures.push("Hide RDP"); }
+ }
if ((user.removeRights & 0x00000200) != 0) { userFeatures.push("No Terminal"); }
if ((user.removeRights & 0x00000400) != 0) { userFeatures.push("No Files"); }
}
@@ -18218,6 +18234,8 @@
x += '
';
}
@@ -20310,6 +20334,8 @@
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 & 0x00001000) != 0) { add += 0x00001000; } // Limited Input Only
+ if ((userinfo.removeRights & 0x00400000) != 0) { add += 0x00400000; } // Hide RDP Sessions
if ((userinfo.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
if ((userinfo.removeRights & 0x00008000) != 0) { substract += 0x00008000; } // No Uninstall
if ((userinfo.removeRights & 0x00020000) != 0) { substract += 0x00020000; } // No Remote Command
diff --git a/webserver.js b/webserver.js
index 60c7cc5c4d..579436771a 100644
--- a/webserver.js
+++ b/webserver.js
@@ -124,6 +124,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
const MESHRIGHT_REMOTECOMMAND = 0x00020000;
const MESHRIGHT_RESETOFF = 0x00040000;
const MESHRIGHT_GUESTSHARING = 0x00080000;
+ const MESHRIGHT_DEVICEDETAILS = 0x00100000;
+ const MESHRIGHT_RELAY = 0x00200000;
+ const MESHRIGHT_HIDERDPSESSIONS = 0x00400000;
const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// Site rights
@@ -3206,6 +3209,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
serverfeatures: serverFeatures,
features: allFeatures.features,
features2: allFeatures.features2,
+ features3: allFeatures.features3,
sessiontime: (args.sessiontime) ? args.sessiontime : 60,
mpspass: args.mpspass,
passRequirements: passRequirements,
@@ -3271,6 +3275,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
obj.getDomainUserFeatures = function (domain, user, req) {
var features = 0;
var features2 = 0;
+ var features3 = 0;
if (obj.args.wanonly == true) { features += 0x00000001; } // WAN-only mode
if (obj.args.lanonly == true) { features += 0x00000002; } // LAN-only mode
if (obj.args.nousers == true) { features += 0x00000004; } // Single user mode
@@ -3343,7 +3348,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
if (domain.devicesearchbargroupname === true) { features2 += 0x10000000; } // Search bar will find by group name too
if (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.duo2factor != false)) && (typeof domain.duo2factor == 'object') && (typeof domain.duo2factor.integrationkey == 'string') && (typeof domain.duo2factor.secretkey == 'string') && (typeof domain.duo2factor.apihostname == 'string')) { features2 += 0x20000000; } // using Duo for 2FA is allowed
if (domain.showmodernuitoggle == true) { features2 += 0x40000000; } // Indicates that the new UI should be shown
- return { features: features, features2: features2 };
+ if (domain.applyfeaturepermissionstorouterandwebtools !== false) {features3 += 0x00000001; }
+ return { features: features, features2: features2, features3 };
}
function handleRootRequestLogin(req, res, domain, hardwareKeyChallenge, passRequirements) {
@@ -8664,6 +8670,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
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 & 0x00001000) != 0) { add += 0x00001000; } // Limited Input Only
+ if ((user.removeRights & 0x00400000) != 0) { add += 0x00400000; } // Hide RDP Sessions
if ((user.removeRights & 0x00000010) != 0) { substract += 0x00000010; } // No Console
if ((user.removeRights & 0x00008000) != 0) { substract += 0x00008000; } // No Uninstall
if ((user.removeRights & 0x00020000) != 0) { substract += 0x00020000; } // No Remote Command