UI customization improvements.
Ylian Saint-Hilaire committed
Nov 5, 2020 at 02:27 UTC
98b39000eb18bd25249336e1b6c476b4f3114775
11 files changed
+72
-39
meshcentral.js
+6
-6
@@ -131,7 +131,7 @@ function CreateMeshCentralServer(config, args) {
131
try { require('./pass').hash('test', function () { }, 0); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
132
133
// Check for invalid arguments
134
- var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'rediraliasport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'showitem', 'listuserids', 'showusergroups', 'shownodes', 'showallmeshes', 'showmeshes', 'showevents', 'showsmbios', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'xinstall', 'xuninstall', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbfix', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'logintoken', 'logintokenkey', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'vaultpushconfigfiles', 'vaultpullconfigfiles', 'vaultdeleteconfigfiles', 'configkey', 'loadconfigfromdb', 'npmpath', 'serverid', 'recordencryptionrecode', 'vault', 'token', 'unsealkey', 'name', 'log', 'dbstats', 'translate', 'createaccount', 'resetaccount', 'pass', 'adminaccount', 'removeaccount', 'domain', 'email'];
134
+ var validArguments = ['_', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'rediraliasport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'showitem', 'listuserids', 'showusergroups', 'shownodes', 'showallmeshes', 'showmeshes', 'showevents', 'showsmbios', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'xinstall', 'xuninstall', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbfix', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'logintoken', 'logintokenkey', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'vaultpushconfigfiles', 'vaultpullconfigfiles', 'vaultdeleteconfigfiles', 'configkey', 'loadconfigfromdb', 'npmpath', 'serverid', 'recordencryptionrecode', 'vault', 'token', 'unsealkey', 'name', 'log', 'dbstats', 'translate', 'createaccount', 'resetaccount', 'pass', 'adminaccount', 'removeaccount', 'domain', 'email'];
135
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
136
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
137
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
@@ -1103,12 +1103,12 @@ function CreateMeshCentralServer(config, args) {
1103
if ((obj.args.ciralocalfqdn != null) && ((obj.args.lanonly == true) || (obj.args.wanonly == true))) { addServerWarning("CIRA local FQDN's ignored when server in LAN-only or WAN-only mode."); }
1104
if ((obj.args.ciralocalfqdn != null) && (obj.args.ciralocalfqdn.split(',').length > 4)) { addServerWarning("Can't have more than 4 CIRA local FQDN's. Ignoring value."); obj.args.ciralocalfqdn = null; }
1105
if (obj.args.ignoreagenthashcheck === true) { addServerWarning("Agent hash checking is being skipped, this is unsafe."); }
1106
- if (obj.args.port == null || typeof obj.args.port != 'number') { if (obj.args.notls == null) { obj.args.port = 443; } else { obj.args.port = 80; } }
1106
+ if (obj.args.port == null || typeof obj.args.port != 'number') { obj.args.port = 443; }
1107
if (obj.args.aliasport != null && (typeof obj.args.aliasport != 'number')) obj.args.aliasport = null;
1108
if (obj.args.mpsport == null || typeof obj.args.mpsport != 'number') obj.args.mpsport = 4433;
1109
if (obj.args.mpsaliasport != null && (typeof obj.args.mpsaliasport != 'number')) obj.args.mpsaliasport = null;
1110
if (obj.args.rediraliasport != null && (typeof obj.args.rediraliasport != 'number')) obj.args.rediraliasport = null;
1111
- if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80;
1111
+ if (obj.args.redirport == null) obj.args.redirport = 80;
1112
if (obj.args.minifycore === 0) obj.args.minifycore = false;
1113
if (typeof args.agentidletimeout != 'number') { args.agentidletimeout = 150000; } else { args.agentidletimeout *= 1000 } // Default agent idle timeout is 2m, 30sec.
1114
@@ -2107,7 +2107,7 @@ function CreateMeshCentralServer(config, args) {
2107
obj.meshToolsBinaries[this.toolname].hashx = this.hashx;
2108
obj.meshToolsBinaries[this.toolname].path = this.agentpath;
2109
obj.meshToolsBinaries[this.toolname].dlname = this.dlname;
2110
- obj.meshToolsBinaries[this.toolname].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?meshaction=' + this.dlname;
2110
+ obj.meshToolsBinaries[this.toolname].url = ('https://' + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?meshaction=' + this.dlname;
2111
var stats = null;
2112
try { stats = obj.fs.statSync(this.agentpath); } catch (e) { }
2113
if (stats != null) { obj.meshToolsBinaries[this.toolname].size = stats.size; }
@@ -2148,7 +2148,7 @@ function CreateMeshCentralServer(config, args) {
2148
obj.meshAgentInstallScripts[this.info.id].hash = this.hash.digest('hex');
2149
obj.meshAgentInstallScripts[this.info.id].path = this.agentpath;
2150
obj.meshAgentInstallScripts[this.info.id].data = this.xdata;
2151
- obj.meshAgentInstallScripts[this.info.id].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?script=' + this.info.id;
2151
+ obj.meshAgentInstallScripts[this.info.id].url = ('https://' + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?script=' + this.info.id;
2152
var stats = null;
2153
try { stats = obj.fs.statSync(this.agentpath); } catch (e) { }
2154
if (stats != null) { obj.meshAgentInstallScripts[this.info.id].size = stats.size; }
@@ -2213,7 +2213,7 @@ function CreateMeshCentralServer(config, args) {
2213
archcount++;
2214
obj.meshAgentBinaries[archid] = Object.assign({}, obj.meshAgentsArchitectureNumbers[archid]);
2215
obj.meshAgentBinaries[archid].path = agentpath;
2216
- obj.meshAgentBinaries[archid].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?id=' + archid;
2216
+ obj.meshAgentBinaries[archid].url = ('http://' + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?id=' + archid;
2217
obj.meshAgentBinaries[archid].size = stats.size;
2218
2219
// If this is a windows binary, pull binary information
meshctrl.js
+28
-2
@@ -272,6 +272,15 @@ if (args['_'].length == 0) {
272
console.log(" --hours [hours] - Validity period in hours or 0 for infinit.");
273
break;
274
}
275
+ case 'showevents': {
276
+ console.log("Show the server's event stream for this user account. Example usage:\r\n");
277
+ console.log(" MeshCtrl ShowEvents");
278
+ console.log(" MeshCtrl ShowEvents --filter nodeconnect");
279
+ console.log(" MeshCtrl ShowEvents --filter uicustomevent,changenode");
280
+ console.log("\r\nOptional arguments:\r\n");
281
+ console.log(" --filter [actions] - Show only specified actions.");
282
+ break;
283
+ }
284
case 'serverinfo': {
285
console.log("Get information on the MeshCentral server, Example usages:\r\n");
286
console.log(" MeshCtrl ServerInfo --loginuser myaccountname --loginpass mypassword");
@@ -625,10 +634,12 @@ if (args['_'].length == 0) {
634
break;
635
}
636
case 'broadcast': {
628
- console.log("Display a message to all logged in users, Example usages:\r\n");
637
+ console.log("Display a message to one or all logged in users, Example usages:\r\n");
638
console.log(" MeshCtrl Broadcast --msg \"This is a test\"");
639
console.log("\r\nRequired arguments:\r\n");
640
console.log(" --msg [message] - Message to display.");
641
+ console.log("\r\nOptional arguments:\r\n");
642
+ console.log(" --user [userid] - Send the message to the speficied user.");
643
break;
644
}
645
case 'deviceinfo': {
@@ -1216,6 +1227,7 @@ function serverConnect() {
1227
}
1228
case 'broadcast': {
1229
var op = { action: 'userbroadcast', msg: args.msg, responseid: 'meshctrl' };
1230
+ if (args.user) { op.userid = args.user; }
1231
ws.send(JSON.stringify(op));
1232
break;
1233
}
@@ -1269,7 +1281,21 @@ function serverConnect() {
1281
var data = null;
1282
try { data = JSON.parse(rawdata); } catch (ex) { }
1283
if (data == null) { console.log('Unable to parse data: ' + rawdata); }
1272
- if (settings.cmd == 'showevents') { console.log(JSON.stringify(data, null, 2)); return; }
1284
+ if (settings.cmd == 'showevents') {
1285
+ if (args.filter == null) {
1286
+ // Display all events
1287
+ console.log(JSON.stringify(data, null, 2));
1288
+ } else {
1289
+ // Display select events
1290
+ var filters = args.filter.split(',');
1291
+ if (typeof data.event == 'object') {
1292
+ if (filters.indexOf(data.event.action) >= 0) { console.log(JSON.stringify(data, null, 2) + '\r\n'); }
1293
+ } else {
1294
+ if (filters.indexOf(data.action) >= 0) { console.log(JSON.stringify(data, null, 2) + '\r\n'); }
1295
+ }
1296
+ }
1297
+ return;
1298
+ }
1299
switch (data.action) {
1300
case 'serverinfo': { // SERVERINFO
1301
settings.currentDomain = data.serverinfo.domain;
meshdesktopmultiplex.js
+1
-1
@@ -984,7 +984,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
984
/*
985
// Validate that the id is valid, we only need to do this on non-authenticated sessions.
986
// TODO: Figure out when this needs to be done.
987
- if ((user == null) && (!parent.args.notls)) {
987
+ if (user == null) {
988
// Check the identifier, if running without TLS, skip this.
989
var ids = obj.id.split(':');
990
if (ids.length != 3) { ws.close(); delete obj.id; return null; } // Invalid ID, drop this.
meshmail.js
+2
-2
@@ -128,10 +128,10 @@ module.exports.CreateMeshMail = function (parent) {
128
var httpsport = (typeof obj.parent.args.aliasport == 'number') ? obj.parent.args.aliasport : obj.parent.args.port;
129
if (domain.dns == null) {
130
// Default domain or subdomain of the default.
131
- options.serverurl = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + obj.parent.certificates.CommonName + ':' + httpsport + domain.url;
131
+ options.serverurl = 'https://' + obj.parent.certificates.CommonName + ':' + httpsport + domain.url;
132
} else {
133
// Domain with a DNS name.
134
- options.serverurl = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + domain.dns + ':' + httpsport + domain.url;
134
+ options.serverurl = 'https://' + domain.dns + ':' + httpsport + domain.url;
135
}
136
if (options.serverurl.endsWith('/')) { options.serverurl = options.serverurl.substring(0, options.serverurl.length - 1); } // Remove the ending / if present
137
for (var i in options) {
meshscanner.js
+4
-4
@@ -175,15 +175,15 @@ module.exports.CreateMeshScanner = function (parent) {
175
var port = (parent.args.aliasport)?parent.args.aliasport:parent.args.port;
176
177
// Build the IPv4 response
178
- var url = (parent.args.notls ? 'ws' : 'wss') + '://%s:' + port + '/agent.ashx';
178
+ var url = 'wss://%s:' + port + '/agent.ashx';
179
obj.multicastPacket4 = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url, 'ascii');
180
- if (parent.certificates.CommonName.indexOf('.') != -1) { url = (parent.args.notls ? 'ws' : 'wss') + '://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; }
180
+ if (parent.certificates.CommonName.indexOf('.') != -1) { url = 'wss://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; }
181
obj.multicastPacket4x = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url + '|' + name + '|' + info, 'ascii');
182
183
// Build the IPv6 response
184
- url = (parent.args.notls ? 'ws' : 'wss') + '://[%s]:' + port + '/agent.ashx';
184
+ url = 'wss://[%s]:' + port + '/agent.ashx';
185
obj.multicastPacket6 = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url, 'ascii');
186
- if (parent.certificates.CommonName.indexOf('.') != -1) { url = (parent.args.notls ? 'ws' : 'wss') + '://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; }
186
+ if (parent.certificates.CommonName.indexOf('.') != -1) { url = 'wss://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; }
187
obj.multicastPacket6x = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url + '|' + name + '|' + info, 'ascii');
188
189
setupServers();
meshuser.js
+7
-5
@@ -457,7 +457,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
457
}
458
if (matchingDomains.length > 0) { serverinfo.amtAcmFqdn = matchingDomains; }
459
}
460
- if (args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = args.redirport; }
460
+ serverinfo.https = true;
461
+ serverinfo.redirport = args.redirport;
462
if (typeof domain.userconsentflags == 'number') { serverinfo.consent = domain.userconsentflags; }
463
if ((typeof domain.usersessionidletimeout == 'number') && (domain.usersessionidletimeout > 0)) { serverinfo.timeout = (domain.usersessionidletimeout * 60 * 1000); }
464
if (user.siteadmin === SITERIGHT_ADMIN) {
@@ -1743,6 +1744,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1744
try {
1745
if (parent.wssessions2[i].domainid == domain.id) {
1746
var sessionUser = parent.users[parent.wssessions2[i].userid];
1747
+ if ((command.userid != null) && (command.userid != sessionUser._id) && (command.userid != sessionUser._id.split('/')[2])) { continue; }
1748
if ((command.target == null) || ((sessionUser.links) != null && (sessionUser.links[command.target] != null))) {
1749
if ((user.groups == null) || (user.groups.length == 0)) {
1750
// We are part of no user groups, send to everyone.
@@ -2662,7 +2664,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2664
var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified
2665
var xdomain = (domain.dns == null) ? domain.id : '';
2666
if (xdomain != '') xdomain += "/";
2665
- var url = "http" + (args.notls ? '' : 's') + "://" + parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name);
2667
+ var url = "https://" + parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name);
2668
2669
// Create the notification message
2670
routeCommandToNode({ 'action': 'openUrl', 'nodeid': command.nodeid, 'userid': user._id, 'username': user.name, 'url': url });
@@ -4570,7 +4572,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4572
var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified
4573
var xdomain = (domain.dns == null) ? domain.id : '';
4574
if (xdomain != '') xdomain += '/';
4573
- var url = 'http' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agentinvite?c=' + inviteCookie;
4575
+ var url = 'https://' + serverName + ':' + httpsPort + '/' + xdomain + 'agentinvite?c=' + inviteCookie;
4576
if (serverName.split('.') == 1) { url = '/' + xdomain + 'agentinvite?c=' + inviteCookie; }
4577
4578
ws.send(JSON.stringify({ action: 'createInviteLink', meshid: command.meshid, url: url, expire: command.expire, cookie: inviteCookie, responseid: command.responseid, tag: command.tag }));
@@ -4725,7 +4727,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4727
var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified
4728
var xdomain = (domain.dns == null) ? domain.id : '';
4729
if (xdomain != '') xdomain += '/';
4728
- var url = 'http' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'desktop?c=' + inviteCookie;
4730
+ var url = 'https://' + serverName + ':' + httpsPort + '/' + xdomain + 'desktop?c=' + inviteCookie;
4731
if (serverName.split('.') == 1) { url = '/' + xdomain + 'desktop?c=' + inviteCookie; }
4732
command.url = url;
4733
ws.send(JSON.stringify(command));
@@ -4819,7 +4821,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4821
var xdomain = (domain.dns == null) ? domain.id : '';
4822
if (xdomain != '') xdomain += '/';
4823
var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified
4822
- r.wsUrl = 'ws' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'mqtt.ashx';
4824
+ r.wsUrl = 'wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'mqtt.ashx';
4825
r.wsTrustedCert = parent.isTrustedCert(domain);
4826
4827
try { ws.send(JSON.stringify(r)); } catch (ex) { }
mstsc.js
+1
-1
@@ -64,7 +64,7 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
64
var options = { rejectUnauthorized: false };
65
if (domain.dns != null) { options.servername = domain.dns; }
66
var protocol = 'wss';
67
- if (args.notls || args.tlsoffload) { protocol = 'ws'; }
67
+ if (args.tlsoffload) { protocol = 'ws'; }
68
var domainadd = '';
69
if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' }
70
var url = protocol + '://127.0.0.1:' + args.port + '/' + domainadd + 'meshrelay.ashx?auth=' + obj.infos.ip;
redirserver.js
+1
-1
@@ -75,7 +75,7 @@ module.exports.CreateRedirServer = function (parent, db, args, func) {
75
parent.letsencrypt.challenge(req.url.slice(leChallengePrefix.length), getCleanHostname(req), function (response) { if (response == null) { res.sendStatus(404); } else { res.send(response); } });
76
} else {
77
// Everything else
78
- var selfurl = ((args.notls !== true) ? (' wss://' + req.headers.host) : (' ws://' + req.headers.host));
78
+ var selfurl = (' wss://' + req.headers.host);
79
res.set({
80
'strict-transport-security': 'max-age=60000; includeSubDomains',
81
'Referrer-Policy': 'no-referrer',
views/default-mobile.handlebars
+7
-1
@@ -3331,7 +3331,13 @@
3331
for (var pid in processes) { p.push({ p: parseInt(pid), c: processes[pid].cmd, d: processes[pid].cmd.toLowerCase(), u: processes[pid].user }); }
3332
if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
3333
var x = '';
3334
- for (var i in p) { if (p[i].p != 0) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + p[i].c + '</div></div>'; } }
3334
+ for (var i in p) {
3335
+ if (p[i].p != 0) {
3336
+ var c = p[i].c;
3337
+ if (c.length > 30) { c = '<span title="' + EscapeHtml(c) + '">' + EscapeHtml(c.substring(0, 30)) + '...</span>' } else { c = EscapeHtml(c); }
3338
+ x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + EscapeHtml(p[i].p) + '</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess(' + EscapeHtml(p[i].p) + ',"' + EscapeHtml(p[i].c) + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? EscapeHtml(p[i].u) : '') + '</div><div>' + c + '</div></div>';
3339
+ }
3340
+ }
3341
QH('DeskToolsProcesses', x);
3342
}
3343
}
views/default.handlebars
+4
-3
@@ -1573,8 +1573,7 @@
1573
if (typeof dialog.elements == 'object') {
1574
for (var i in dialog.elements) {
1575
var elem = dialog.elements[i];
1576
- if (elem.type == 'text') { t.values[i] = Q('cui:' + i).value; }
1577
- if (elem.type == 'droplist') { t.values[i] = Q('cui:' + i).value; }
1576
+ if ((elem.type == 'droplist') || (elem.type == 'textarea') || (elem.type == 'text')) { t.values[i] = Q('cui:' + i).value; }
1577
}
1578
}
1579
meshserver.send(t);
@@ -5790,7 +5789,9 @@
5789
// Custom UI
5790
if ((customui != null) && (customui.devicebuttons != null)) {
5791
for (var i in customui.devicebuttons) {
5793
- x += '<input id="cui:' + i + '" type="button" value="' + customui.devicebuttons[i].name + '" onclick=customUIAction(event,"devicebuttons") />';
5792
+ if ((customui.devicebuttons[i].showif == null) || ((mesh != null) && (customui.devicebuttons[i].showif == mesh._id)) || (customui.devicebuttons[i].showif == currentNode._id)) {
5793
+ x += '<input id="cui:' + i + '" type="button" value="' + customui.devicebuttons[i].name + '" onclick=customUIAction(event,"devicebuttons") />';
5794
+ }
5795
}
5796
}
5797
webserver.js
+11
-13
@@ -1729,7 +1729,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1729
if (typeof installflags != 'number') { installflags = 0; }
1730
parent.debug('web', 'handleAgentInviteRequest using cookie.');
1731
var meshcookie = parent.encodeCookie({ m: mesh._id.split('/')[2] }, parent.invitationLinkEncryptionKey);
1732
- render(req, res, getRenderPage('agentinvite', req, domain), getRenderArgs({ meshid: meshcookie, serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name).replace(/'/g, '%27'), installflags: installflags }, req, domain));
1732
+ render(req, res, getRenderPage('agentinvite', req, domain), getRenderArgs({ meshid: meshcookie, serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: 1, servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name).replace(/'/g, '%27'), installflags: installflags }, req, domain));
1733
} else if (req.query.m != null) {
1734
// The MeshId is specified in the query string, use that
1735
var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.m.toLowerCase()];
@@ -1739,7 +1739,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1739
if (typeof installflags != 'number') { installflags = 0; }
1740
parent.debug('web', 'handleAgentInviteRequest using meshid.');
1741
var meshcookie = parent.encodeCookie({ m: mesh._id.split('/')[2] }, parent.invitationLinkEncryptionKey);
1742
- render(req, res, getRenderPage('agentinvite', req, domain), getRenderArgs({ meshid: meshcookie, serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name).replace(/'/g, '%27'), installflags: installflags }, req, domain));
1742
+ render(req, res, getRenderPage('agentinvite', req, domain), getRenderArgs({ meshid: meshcookie, serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: 1, servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name).replace(/'/g, '%27'), installflags: installflags }, req, domain));
1743
}
1744
}
1745
@@ -2527,7 +2527,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2527
2528
// Return true if it looks like we are using a real TLS certificate.
2529
obj.isTrustedCert = function (domain) {
2530
- if (obj.args.notls == true) return false; // We are not using TLS, so not trusted cert.
2530
if ((domain != null) && (typeof domain.trustedcert == 'boolean')) return domain.trustedcert; // If the status of the cert specified, use that.
2531
if (typeof obj.args.trustedcert == 'boolean') return obj.args.trustedcert; // If the status of the cert specified, use that.
2532
if (obj.args.tlsoffload != null) return true; // We are using TLS offload, a real cert is likely used.
@@ -2540,7 +2539,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2539
// Get the link to the root certificate if needed
2540
function getRootCertLink() {
2541
// Check if the HTTPS certificate is issued from MeshCentralRoot, if so, add download link to root certificate.
2543
- if ((obj.args.notls == null) && (obj.args.tlsoffload == null) && (obj.parent.config.letsencrypt == null) && (obj.tlsSniCredentials == null) && (obj.certificates.WebIssuer.indexOf('MeshCentralRoot-') == 0) && (obj.certificates.CommonName.indexOf('.') != -1)) { return '<a href=/MeshServerRootCert.cer title="Download the root certificate for this server">Root Certificate</a>'; }
2542
+ if ((obj.args.tlsoffload == null) && (obj.parent.config.letsencrypt == null) && (obj.tlsSniCredentials == null) && (obj.certificates.WebIssuer.indexOf('MeshCentralRoot-') == 0) && (obj.certificates.CommonName.indexOf('.') != -1)) { return '<a href=/MeshServerRootCert.cer title="Download the root certificate for this server">Root Certificate</a>'; }
2543
return '';
2544
}
2545
@@ -4106,7 +4105,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4105
var xdomain = (domain.dns == null) ? domain.id : '';
4106
if (xdomain != '') xdomain += '/';
4107
var meshsettings = 'MeshName=' + mesh.name + '\r\nMeshType=' + mesh.mtype + '\r\nMeshID=0x' + meshidhex + '\r\nServerID=' + serveridhex + '\r\n';
4109
- if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else {
4108
+ if (obj.args.lanonly != true) { meshsettings += 'MeshServer=wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else {
4109
meshsettings += 'MeshServer=local\r\n';
4110
if ((obj.args.localdiscovery != null) && (typeof obj.args.localdiscovery.key == 'string') && (obj.args.localdiscovery.key.length > 0)) { meshsettings += 'DiscoveryKey=' + obj.args.localdiscovery.key + '\r\n'; }
4111
}
@@ -4227,7 +4226,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4226
if (user != null) { meshaction.username = user.name; }
4227
if (req.query.key != null) { meshaction.loginKey = req.query.key; }
4228
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
4230
- if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
4229
+ if (obj.args.lanonly != true) { meshaction.serverUrl = 'wss://' + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
4230
4231
setContentDispositionHeader(res, 'application/octet-stream', 'meshaction.txt', null, 'meshaction.txt');
4232
res.send(JSON.stringify(meshaction, null, ' '));
@@ -4243,7 +4242,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4242
if (user != null) { meshaction.username = user.name; }
4243
if (req.query.key != null) { meshaction.loginKey = req.query.key; }
4244
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
4246
- if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
4245
+ if (obj.args.lanonly != true) { meshaction.serverUrl = 'wss://' + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
4246
setContentDispositionHeader(res, 'application/octet-stream', 'meshaction.txt', null, 'meshaction.txt');
4247
res.send(JSON.stringify(meshaction, null, ' '));
4248
} else if (req.query.meshaction == 'winrouter') {
@@ -4407,7 +4406,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4406
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
4407
if (obj.args.agentport != null) { httpsPort = obj.args.agentport; } // If an agent only port is enabled, use that.
4408
if (obj.args.agentaliasport != null) { httpsPort = obj.args.agentaliasport; } // If an agent alias port is specified, use that.
4410
- if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else {
4409
+ if (obj.args.lanonly != true) { meshsettings += 'MeshServer=wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else {
4410
meshsettings += 'MeshServer=local\r\n';
4411
if ((obj.args.localdiscovery != null) && (typeof obj.args.localdiscovery.key == 'string') && (obj.args.localdiscovery.key.length > 0)) { meshsettings += 'DiscoveryKey=' + obj.args.localdiscovery.key + '\r\n'; }
4412
}
@@ -4499,7 +4498,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4498
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
4499
if (obj.args.agentport != null) { httpsPort = obj.args.agentport; } // If an agent only port is enabled, use that.
4500
if (obj.args.agentaliasport != null) { httpsPort = obj.args.agentaliasport; } // If an agent alias port is specified, use that.
4502
- if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else {
4501
+ if (obj.args.lanonly != true) { meshsettings += 'MeshServer=wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else {
4502
meshsettings += 'MeshServer=local\r\n';
4503
if ((obj.args.localdiscovery != null) && (typeof obj.args.localdiscovery.key == 'string') && (obj.args.localdiscovery.key.length > 0)) { meshsettings += 'DiscoveryKey=' + obj.args.localdiscovery.key + '\r\n'; }
4504
}
@@ -4599,7 +4598,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4598
// Starts the HTTPS server, this should be called after the user/mesh tables are loaded
4599
function serverStart() {
4600
// Start the server, only after users and meshes are loaded from the database.
4602
- if (obj.args.notls || obj.args.tlsoffload) {
4601
+ if (obj.args.tlsoffload) {
4602
// Setup the HTTP server without TLS
4603
obj.expressWs = require('express-ws')(obj.app, null, { wsOptions: { perMessageDeflate: (args.wscompression === true) } });
4604
} else {
@@ -4619,7 +4618,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4618
// Start a second agent-only server if needed
4619
if (obj.args.agentport) {
4620
var agentPortTls = true;
4622
- if ((obj.args.notls == 1) || (obj.args.notls == true)) { agentPortTls = false; }
4621
if (obj.args.tlsoffload != null) { agentPortTls = false; }
4622
if (typeof obj.args.agentporttls == 'boolean') { agentPortTls = obj.args.agentporttls; }
4623
if (obj.certificates.webdefault == null) { agentPortTls = false; }
@@ -4651,7 +4649,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4649
name: 'xid', // Recommended security practice to not use the default cookie name
4650
httpOnly: true,
4651
keys: [obj.args.sessionkey], // If multiple instances of this server are behind a load-balancer, this secret must be the same for all instances
4654
- secure: ((obj.args.notls != true) && (obj.args.tlsoffload == null)) // Use this cookie only over TLS (Check this: https://expressjs.com/en/guide/behind-proxies.html)
4652
+ secure: (obj.args.tlsoffload == null) // Use this cookie only over TLS (Check this: https://expressjs.com/en/guide/behind-proxies.html)
4653
}
4654
if (obj.args.sessionsamesite != null) { sessionOptions.sameSite = obj.args.sessionsamesite; } else { sessionOptions.sameSite = 'strict'; }
4655
if (obj.args.sessiontime != null) { sessionOptions.maxAge = (obj.args.sessiontime * 60 * 1000); }
@@ -4696,7 +4694,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4694
} else {
4695
// Use default security headers
4696
var geourl = (domain.geolocation ? ' *.openstreetmap.org' : '');
4699
- var selfurl = ((args.notls !== true) ? (' wss://' + req.headers.host) : (' ws://' + req.headers.host));
4697
+ var selfurl = (' wss://' + req.headers.host);
4698
var headers = {
4699
'Referrer-Policy': 'no-referrer',
4700
'X-XSS-Protection': '1; mode=block',