diff --git a/meshcentral.js b/meshcentral.js index 7ee3789e..d1488adc 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -131,7 +131,7 @@ function CreateMeshCentralServer(config, args) { 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. // Check for invalid arguments - 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']; + 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']; 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; } } 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; } 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) { 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."); } 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; } if (obj.args.ignoreagenthashcheck === true) { addServerWarning("Agent hash checking is being skipped, this is unsafe."); } - if (obj.args.port == null || typeof obj.args.port != 'number') { if (obj.args.notls == null) { obj.args.port = 443; } else { obj.args.port = 80; } } + if (obj.args.port == null || typeof obj.args.port != 'number') { obj.args.port = 443; } if (obj.args.aliasport != null && (typeof obj.args.aliasport != 'number')) obj.args.aliasport = null; if (obj.args.mpsport == null || typeof obj.args.mpsport != 'number') obj.args.mpsport = 4433; if (obj.args.mpsaliasport != null && (typeof obj.args.mpsaliasport != 'number')) obj.args.mpsaliasport = null; if (obj.args.rediraliasport != null && (typeof obj.args.rediraliasport != 'number')) obj.args.rediraliasport = null; - if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80; + if (obj.args.redirport == null) obj.args.redirport = 80; if (obj.args.minifycore === 0) obj.args.minifycore = false; if (typeof args.agentidletimeout != 'number') { args.agentidletimeout = 150000; } else { args.agentidletimeout *= 1000 } // Default agent idle timeout is 2m, 30sec. @@ -2107,7 +2107,7 @@ function CreateMeshCentralServer(config, args) { obj.meshToolsBinaries[this.toolname].hashx = this.hashx; obj.meshToolsBinaries[this.toolname].path = this.agentpath; obj.meshToolsBinaries[this.toolname].dlname = this.dlname; - 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; + obj.meshToolsBinaries[this.toolname].url = ('https://' + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?meshaction=' + this.dlname; var stats = null; try { stats = obj.fs.statSync(this.agentpath); } catch (e) { } if (stats != null) { obj.meshToolsBinaries[this.toolname].size = stats.size; } @@ -2148,7 +2148,7 @@ function CreateMeshCentralServer(config, args) { obj.meshAgentInstallScripts[this.info.id].hash = this.hash.digest('hex'); obj.meshAgentInstallScripts[this.info.id].path = this.agentpath; obj.meshAgentInstallScripts[this.info.id].data = this.xdata; - 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; + 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; var stats = null; try { stats = obj.fs.statSync(this.agentpath); } catch (e) { } if (stats != null) { obj.meshAgentInstallScripts[this.info.id].size = stats.size; } @@ -2213,7 +2213,7 @@ function CreateMeshCentralServer(config, args) { archcount++; obj.meshAgentBinaries[archid] = Object.assign({}, obj.meshAgentsArchitectureNumbers[archid]); obj.meshAgentBinaries[archid].path = agentpath; - 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; + obj.meshAgentBinaries[archid].url = ('http://' + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?id=' + archid; obj.meshAgentBinaries[archid].size = stats.size; // If this is a windows binary, pull binary information diff --git a/meshctrl.js b/meshctrl.js index d11eb483..d30e2067 100644 --- a/meshctrl.js +++ b/meshctrl.js @@ -272,6 +272,15 @@ if (args['_'].length == 0) { console.log(" --hours [hours] - Validity period in hours or 0 for infinit."); break; } + case 'showevents': { + console.log("Show the server's event stream for this user account. Example usage:\r\n"); + console.log(" MeshCtrl ShowEvents"); + console.log(" MeshCtrl ShowEvents --filter nodeconnect"); + console.log(" MeshCtrl ShowEvents --filter uicustomevent,changenode"); + console.log("\r\nOptional arguments:\r\n"); + console.log(" --filter [actions] - Show only specified actions."); + break; + } case 'serverinfo': { console.log("Get information on the MeshCentral server, Example usages:\r\n"); console.log(" MeshCtrl ServerInfo --loginuser myaccountname --loginpass mypassword"); @@ -625,10 +634,12 @@ if (args['_'].length == 0) { break; } case 'broadcast': { - console.log("Display a message to all logged in users, Example usages:\r\n"); + console.log("Display a message to one or all logged in users, Example usages:\r\n"); console.log(" MeshCtrl Broadcast --msg \"This is a test\""); console.log("\r\nRequired arguments:\r\n"); console.log(" --msg [message] - Message to display."); + console.log("\r\nOptional arguments:\r\n"); + console.log(" --user [userid] - Send the message to the speficied user."); break; } case 'deviceinfo': { @@ -1216,6 +1227,7 @@ function serverConnect() { } case 'broadcast': { var op = { action: 'userbroadcast', msg: args.msg, responseid: 'meshctrl' }; + if (args.user) { op.userid = args.user; } ws.send(JSON.stringify(op)); break; } @@ -1269,7 +1281,21 @@ function serverConnect() { var data = null; try { data = JSON.parse(rawdata); } catch (ex) { } if (data == null) { console.log('Unable to parse data: ' + rawdata); } - if (settings.cmd == 'showevents') { console.log(JSON.stringify(data, null, 2)); return; } + if (settings.cmd == 'showevents') { + if (args.filter == null) { + // Display all events + console.log(JSON.stringify(data, null, 2)); + } else { + // Display select events + var filters = args.filter.split(','); + if (typeof data.event == 'object') { + if (filters.indexOf(data.event.action) >= 0) { console.log(JSON.stringify(data, null, 2) + '\r\n'); } + } else { + if (filters.indexOf(data.action) >= 0) { console.log(JSON.stringify(data, null, 2) + '\r\n'); } + } + } + return; + } switch (data.action) { case 'serverinfo': { // SERVERINFO settings.currentDomain = data.serverinfo.domain; diff --git a/meshdesktopmultiplex.js b/meshdesktopmultiplex.js index 80be00c6..0ae2a6d9 100644 --- a/meshdesktopmultiplex.js +++ b/meshdesktopmultiplex.js @@ -984,7 +984,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { /* // Validate that the id is valid, we only need to do this on non-authenticated sessions. // TODO: Figure out when this needs to be done. - if ((user == null) && (!parent.args.notls)) { + if (user == null) { // Check the identifier, if running without TLS, skip this. var ids = obj.id.split(':'); if (ids.length != 3) { ws.close(); delete obj.id; return null; } // Invalid ID, drop this. diff --git a/meshmail.js b/meshmail.js index 9df1578c..73c9a2b0 100644 --- a/meshmail.js +++ b/meshmail.js @@ -128,10 +128,10 @@ module.exports.CreateMeshMail = function (parent) { var httpsport = (typeof obj.parent.args.aliasport == 'number') ? obj.parent.args.aliasport : obj.parent.args.port; if (domain.dns == null) { // Default domain or subdomain of the default. - options.serverurl = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + obj.parent.certificates.CommonName + ':' + httpsport + domain.url; + options.serverurl = 'https://' + obj.parent.certificates.CommonName + ':' + httpsport + domain.url; } else { // Domain with a DNS name. - options.serverurl = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + domain.dns + ':' + httpsport + domain.url; + options.serverurl = 'https://' + domain.dns + ':' + httpsport + domain.url; } if (options.serverurl.endsWith('/')) { options.serverurl = options.serverurl.substring(0, options.serverurl.length - 1); } // Remove the ending / if present for (var i in options) { diff --git a/meshscanner.js b/meshscanner.js index c12d3ce1..c985452c 100644 --- a/meshscanner.js +++ b/meshscanner.js @@ -175,15 +175,15 @@ module.exports.CreateMeshScanner = function (parent) { var port = (parent.args.aliasport)?parent.args.aliasport:parent.args.port; // Build the IPv4 response - var url = (parent.args.notls ? 'ws' : 'wss') + '://%s:' + port + '/agent.ashx'; + var url = 'wss://%s:' + port + '/agent.ashx'; obj.multicastPacket4 = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url, 'ascii'); - if (parent.certificates.CommonName.indexOf('.') != -1) { url = (parent.args.notls ? 'ws' : 'wss') + '://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; } + if (parent.certificates.CommonName.indexOf('.') != -1) { url = 'wss://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; } obj.multicastPacket4x = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url + '|' + name + '|' + info, 'ascii'); // Build the IPv6 response - url = (parent.args.notls ? 'ws' : 'wss') + '://[%s]:' + port + '/agent.ashx'; + url = 'wss://[%s]:' + port + '/agent.ashx'; obj.multicastPacket6 = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url, 'ascii'); - if (parent.certificates.CommonName.indexOf('.') != -1) { url = (parent.args.notls ? 'ws' : 'wss') + '://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; } + if (parent.certificates.CommonName.indexOf('.') != -1) { url = 'wss://' + parent.certificates.CommonName + ':' + port + '/agent.ashx'; } obj.multicastPacket6x = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url + '|' + name + '|' + info, 'ascii'); setupServers(); diff --git a/meshuser.js b/meshuser.js index 2a3f29cc..29ed0fbf 100644 --- a/meshuser.js +++ b/meshuser.js @@ -457,7 +457,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } if (matchingDomains.length > 0) { serverinfo.amtAcmFqdn = matchingDomains; } } - if (args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = args.redirport; } + serverinfo.https = true; + serverinfo.redirport = args.redirport; if (typeof domain.userconsentflags == 'number') { serverinfo.consent = domain.userconsentflags; } if ((typeof domain.usersessionidletimeout == 'number') && (domain.usersessionidletimeout > 0)) { serverinfo.timeout = (domain.usersessionidletimeout * 60 * 1000); } if (user.siteadmin === SITERIGHT_ADMIN) { @@ -1743,6 +1744,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use try { if (parent.wssessions2[i].domainid == domain.id) { var sessionUser = parent.users[parent.wssessions2[i].userid]; + if ((command.userid != null) && (command.userid != sessionUser._id) && (command.userid != sessionUser._id.split('/')[2])) { continue; } if ((command.target == null) || ((sessionUser.links) != null && (sessionUser.links[command.target] != null))) { if ((user.groups == null) || (user.groups.length == 0)) { // 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 var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified var xdomain = (domain.dns == null) ? domain.id : ''; if (xdomain != '') xdomain += "/"; - var url = "http" + (args.notls ? '' : 's') + "://" + parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name); + var url = "https://" + parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name); // Create the notification message 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 var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified var xdomain = (domain.dns == null) ? domain.id : ''; if (xdomain != '') xdomain += '/'; - var url = 'http' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agentinvite?c=' + inviteCookie; + var url = 'https://' + serverName + ':' + httpsPort + '/' + xdomain + 'agentinvite?c=' + inviteCookie; if (serverName.split('.') == 1) { url = '/' + xdomain + 'agentinvite?c=' + inviteCookie; } 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 var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified var xdomain = (domain.dns == null) ? domain.id : ''; if (xdomain != '') xdomain += '/'; - var url = 'http' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'desktop?c=' + inviteCookie; + var url = 'https://' + serverName + ':' + httpsPort + '/' + xdomain + 'desktop?c=' + inviteCookie; if (serverName.split('.') == 1) { url = '/' + xdomain + 'desktop?c=' + inviteCookie; } command.url = url; ws.send(JSON.stringify(command)); @@ -4819,7 +4821,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var xdomain = (domain.dns == null) ? domain.id : ''; if (xdomain != '') xdomain += '/'; var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified - r.wsUrl = 'ws' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'mqtt.ashx'; + r.wsUrl = 'wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'mqtt.ashx'; r.wsTrustedCert = parent.isTrustedCert(domain); try { ws.send(JSON.stringify(r)); } catch (ex) { } diff --git a/mstsc.js b/mstsc.js index 3424ba5b..d737236e 100644 --- a/mstsc.js +++ b/mstsc.js @@ -64,7 +64,7 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) { var options = { rejectUnauthorized: false }; if (domain.dns != null) { options.servername = domain.dns; } var protocol = 'wss'; - if (args.notls || args.tlsoffload) { protocol = 'ws'; } + if (args.tlsoffload) { protocol = 'ws'; } var domainadd = ''; if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' } var url = protocol + '://127.0.0.1:' + args.port + '/' + domainadd + 'meshrelay.ashx?auth=' + obj.infos.ip; diff --git a/redirserver.js b/redirserver.js index 10eacc38..5a48fd6a 100644 --- a/redirserver.js +++ b/redirserver.js @@ -75,7 +75,7 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { parent.letsencrypt.challenge(req.url.slice(leChallengePrefix.length), getCleanHostname(req), function (response) { if (response == null) { res.sendStatus(404); } else { res.send(response); } }); } else { // Everything else - var selfurl = ((args.notls !== true) ? (' wss://' + req.headers.host) : (' ws://' + req.headers.host)); + var selfurl = (' wss://' + req.headers.host); res.set({ 'strict-transport-security': 'max-age=60000; includeSubDomains', 'Referrer-Policy': 'no-referrer', diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index 041bfa94..21b22bca 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -3331,7 +3331,13 @@ for (var pid in processes) { p.push({ p: parseInt(pid), c: processes[pid].cmd, d: processes[pid].cmd.toLowerCase(), u: processes[pid].user }); } if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); } var x = ''; - for (var i in p) { if (p[i].p != 0) { x += '
' + p[i].p + '
' + (p[i].u ? p[i].u : '') + '
' + p[i].c + '
'; } } + for (var i in p) { + if (p[i].p != 0) { + var c = p[i].c; + if (c.length > 30) { c = '' + EscapeHtml(c.substring(0, 30)) + '...' } else { c = EscapeHtml(c); } + x += '
' + EscapeHtml(p[i].p) + '
' + (p[i].u ? EscapeHtml(p[i].u) : '') + '
' + c + '
'; + } + } QH('DeskToolsProcesses', x); } } diff --git a/views/default.handlebars b/views/default.handlebars index f982323e..9baa2445 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1573,8 +1573,7 @@ if (typeof dialog.elements == 'object') { for (var i in dialog.elements) { var elem = dialog.elements[i]; - if (elem.type == 'text') { t.values[i] = Q('cui:' + i).value; } - if (elem.type == 'droplist') { t.values[i] = Q('cui:' + i).value; } + if ((elem.type == 'droplist') || (elem.type == 'textarea') || (elem.type == 'text')) { t.values[i] = Q('cui:' + i).value; } } } meshserver.send(t); @@ -5790,7 +5789,9 @@ // Custom UI if ((customui != null) && (customui.devicebuttons != null)) { for (var i in customui.devicebuttons) { - x += ''; + if ((customui.devicebuttons[i].showif == null) || ((mesh != null) && (customui.devicebuttons[i].showif == mesh._id)) || (customui.devicebuttons[i].showif == currentNode._id)) { + x += ''; + } } } diff --git a/webserver.js b/webserver.js index 8ad5186e..cac18da1 100644 --- a/webserver.js +++ b/webserver.js @@ -1729,7 +1729,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (typeof installflags != 'number') { installflags = 0; } parent.debug('web', 'handleAgentInviteRequest using cookie.'); var meshcookie = parent.encodeCookie({ m: mesh._id.split('/')[2] }, parent.invitationLinkEncryptionKey); - 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)); + 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)); } else if (req.query.m != null) { // The MeshId is specified in the query string, use that var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.m.toLowerCase()]; @@ -1739,7 +1739,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (typeof installflags != 'number') { installflags = 0; } parent.debug('web', 'handleAgentInviteRequest using meshid.'); var meshcookie = parent.encodeCookie({ m: mesh._id.split('/')[2] }, parent.invitationLinkEncryptionKey); - 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)); + 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)); } } @@ -2527,7 +2527,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Return true if it looks like we are using a real TLS certificate. obj.isTrustedCert = function (domain) { - if (obj.args.notls == true) return false; // We are not using TLS, so not trusted cert. if ((domain != null) && (typeof domain.trustedcert == 'boolean')) return domain.trustedcert; // If the status of the cert specified, use that. if (typeof obj.args.trustedcert == 'boolean') return obj.args.trustedcert; // If the status of the cert specified, use that. 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) { // Get the link to the root certificate if needed function getRootCertLink() { // Check if the HTTPS certificate is issued from MeshCentralRoot, if so, add download link to root certificate. - 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 'Root Certificate'; } + 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 'Root Certificate'; } return ''; } @@ -4106,7 +4105,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var xdomain = (domain.dns == null) ? domain.id : ''; if (xdomain != '') xdomain += '/'; var meshsettings = 'MeshName=' + mesh.name + '\r\nMeshType=' + mesh.mtype + '\r\nMeshID=0x' + meshidhex + '\r\nServerID=' + serveridhex + '\r\n'; - if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { + if (obj.args.lanonly != true) { meshsettings += 'MeshServer=wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { meshsettings += 'MeshServer=local\r\n'; 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'; } } @@ -4227,7 +4226,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (user != null) { meshaction.username = user.name; } if (req.query.key != null) { meshaction.loginKey = req.query.key; } var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified - if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } + if (obj.args.lanonly != true) { meshaction.serverUrl = 'wss://' + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } setContentDispositionHeader(res, 'application/octet-stream', 'meshaction.txt', null, 'meshaction.txt'); res.send(JSON.stringify(meshaction, null, ' ')); @@ -4243,7 +4242,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (user != null) { meshaction.username = user.name; } if (req.query.key != null) { meshaction.loginKey = req.query.key; } var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified - if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } + if (obj.args.lanonly != true) { meshaction.serverUrl = 'wss://' + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } setContentDispositionHeader(res, 'application/octet-stream', 'meshaction.txt', null, 'meshaction.txt'); res.send(JSON.stringify(meshaction, null, ' ')); } else if (req.query.meshaction == 'winrouter') { @@ -4407,7 +4406,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified if (obj.args.agentport != null) { httpsPort = obj.args.agentport; } // If an agent only port is enabled, use that. if (obj.args.agentaliasport != null) { httpsPort = obj.args.agentaliasport; } // If an agent alias port is specified, use that. - if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { + if (obj.args.lanonly != true) { meshsettings += 'MeshServer=wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { meshsettings += 'MeshServer=local\r\n'; 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'; } } @@ -4499,7 +4498,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified if (obj.args.agentport != null) { httpsPort = obj.args.agentport; } // If an agent only port is enabled, use that. if (obj.args.agentaliasport != null) { httpsPort = obj.args.agentaliasport; } // If an agent alias port is specified, use that. - if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { + if (obj.args.lanonly != true) { meshsettings += 'MeshServer=wss://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { meshsettings += 'MeshServer=local\r\n'; 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'; } } @@ -4599,7 +4598,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Starts the HTTPS server, this should be called after the user/mesh tables are loaded function serverStart() { // Start the server, only after users and meshes are loaded from the database. - if (obj.args.notls || obj.args.tlsoffload) { + if (obj.args.tlsoffload) { // Setup the HTTP server without TLS obj.expressWs = require('express-ws')(obj.app, null, { wsOptions: { perMessageDeflate: (args.wscompression === true) } }); } else { @@ -4619,7 +4618,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Start a second agent-only server if needed if (obj.args.agentport) { var agentPortTls = true; - if ((obj.args.notls == 1) || (obj.args.notls == true)) { agentPortTls = false; } if (obj.args.tlsoffload != null) { agentPortTls = false; } if (typeof obj.args.agentporttls == 'boolean') { agentPortTls = obj.args.agentporttls; } if (obj.certificates.webdefault == null) { agentPortTls = false; } @@ -4651,7 +4649,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { name: 'xid', // Recommended security practice to not use the default cookie name httpOnly: true, keys: [obj.args.sessionkey], // If multiple instances of this server are behind a load-balancer, this secret must be the same for all instances - 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) + secure: (obj.args.tlsoffload == null) // Use this cookie only over TLS (Check this: https://expressjs.com/en/guide/behind-proxies.html) } if (obj.args.sessionsamesite != null) { sessionOptions.sameSite = obj.args.sessionsamesite; } else { sessionOptions.sameSite = 'strict'; } if (obj.args.sessiontime != null) { sessionOptions.maxAge = (obj.args.sessiontime * 60 * 1000); } @@ -4696,7 +4694,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } else { // Use default security headers var geourl = (domain.geolocation ? ' *.openstreetmap.org' : ''); - var selfurl = ((args.notls !== true) ? (' wss://' + req.headers.host) : (' ws://' + req.headers.host)); + var selfurl = (' wss://' + req.headers.host); var headers = { 'Referrer-Policy': 'no-referrer', 'X-XSS-Protection': '1; mode=block',