mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-01-11 15:03:20 -05:00
Merge branch 'Ylianst:master' into master
This commit is contained in:
commit
6cb08efde2
@ -90,7 +90,9 @@
|
||||
"agentVersion": "Neue Version",
|
||||
"elevation": "Zum Installieren/Deinstallieren dieser Software sind erhöhte Berechtigungen erforderlich.",
|
||||
"graphicalerror": "Die grafische Version dieses Installationsprogramms kann auf diesem System nicht ausgeführt werden",
|
||||
"description": "Klicken Sie auf die Schaltflächen unten, um diese Fernverwaltungssoftware zu installieren oder zu deinstallieren. Nach der Installation wird diese Software im Hintergrund ausgeführt, sodass dieser Computer von einem entfernten Administrator verwaltet und gesteuert werden kann."
|
||||
"description": "Klicken Sie auf die Schaltflächen unten, um diese Fernverwaltungssoftware zu installieren oder zu deinstallieren. Nach der Installation wird diese Software im Hintergrund ausgeführt, sodass dieser Computer von einem entfernten Administrator verwaltet und gesteuert werden kann.",
|
||||
"connectionDetailsButton": "Verbindungsinformationen...",
|
||||
"connectionDetailsTitle": "Verbindungsinformationen"
|
||||
},
|
||||
"es": {
|
||||
"agent": "Agente",
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -3177,30 +3177,43 @@ function openUserDesktopUrl(url) {
|
||||
var uid = require('user-sessions').consoleUid();
|
||||
var user = require('user-sessions').getUsername(uid);
|
||||
var domain = require('user-sessions').getDomain(uid);
|
||||
var taskoptions = { env: { _target: process.env['windir'] + '\\system32\\cmd.exe', _args: '/C START ' + url.split('&').join('^&'), _user: '"' + domain + '\\' + user + '"' } };
|
||||
for (var c1e in process.env) {
|
||||
taskoptions.env[c1e] = process.env[c1e];
|
||||
}
|
||||
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-'], taskoptions);
|
||||
child.stderr.on('data', function (c) { });
|
||||
child.stdout.on('data', function (c) { });
|
||||
child.stdin.write('SCHTASKS /CREATE /F /TN MeshChatTask /SC ONCE /ST 00:00 ');
|
||||
if (user) { child.stdin.write('/RU $env:_user '); }
|
||||
child.stdin.write('/TR "$env:_target $env:_args"\r\n');
|
||||
child.stdin.write('$ts = New-Object -ComObject Schedule.service\r\n');
|
||||
child.stdin.write('$ts.connect()\r\n');
|
||||
child.stdin.write('$tsfolder = $ts.getfolder("\\")\r\n');
|
||||
child.stdin.write('$task = $tsfolder.GetTask("MeshChatTask")\r\n');
|
||||
child.stdin.write('$taskdef = $task.Definition\r\n');
|
||||
child.stdin.write('$taskdef.Settings.StopIfGoingOnBatteries = $false\r\n');
|
||||
child.stdin.write('$taskdef.Settings.DisallowStartIfOnBatteries = $false\r\n');
|
||||
child.stdin.write('$taskdef.Actions.Item(1).Path = $env:_target\r\n');
|
||||
child.stdin.write('$taskdef.Actions.Item(1).Arguments = $env:_args\r\n');
|
||||
child.stdin.write('$tsfolder.RegisterTaskDefinition($task.Name, $taskdef, 4, $null, $null, $null)\r\n');
|
||||
var task = { name: 'MeshChatTask', user: user, domain: domain, execPath: process.env['windir'] + '\\system32\\cmd.exe', arguments: ['/C START ' + url.split('&').join('^&')] };
|
||||
|
||||
child.stdin.write('SCHTASKS /RUN /TN MeshChatTask\r\n');
|
||||
child.stdin.write('SCHTASKS /DELETE /F /TN MeshChatTask\r\nexit\r\n');
|
||||
child.waitExit();
|
||||
try
|
||||
{
|
||||
require('win-tasks').addTask(task);
|
||||
require('win-tasks').getTask({ name: 'MeshChatTask' }).run();
|
||||
require('win-tasks').deleteTask('MeshChatTask');
|
||||
return (true);
|
||||
}
|
||||
catch(zz)
|
||||
{
|
||||
var taskoptions = { env: { _target: process.env['windir'] + '\\system32\\cmd.exe', _args: '/C START ' + url.split('&').join('^&'), _user: '"' + domain + '\\' + user + '"' } };
|
||||
for (var c1e in process.env)
|
||||
{
|
||||
taskoptions.env[c1e] = process.env[c1e];
|
||||
}
|
||||
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-'], taskoptions);
|
||||
child.stderr.on('data', function (c) { });
|
||||
child.stdout.on('data', function (c) { });
|
||||
child.stdin.write('SCHTASKS /CREATE /F /TN MeshChatTask /SC ONCE /ST 00:00 ');
|
||||
if (user) { child.stdin.write('/RU $env:_user '); }
|
||||
child.stdin.write('/TR "$env:_target $env:_args"\r\n');
|
||||
child.stdin.write('$ts = New-Object -ComObject Schedule.service\r\n');
|
||||
child.stdin.write('$ts.connect()\r\n');
|
||||
child.stdin.write('$tsfolder = $ts.getfolder("\\")\r\n');
|
||||
child.stdin.write('$task = $tsfolder.GetTask("MeshChatTask")\r\n');
|
||||
child.stdin.write('$taskdef = $task.Definition\r\n');
|
||||
child.stdin.write('$taskdef.Settings.StopIfGoingOnBatteries = $false\r\n');
|
||||
child.stdin.write('$taskdef.Settings.DisallowStartIfOnBatteries = $false\r\n');
|
||||
child.stdin.write('$taskdef.Actions.Item(1).Path = $env:_target\r\n');
|
||||
child.stdin.write('$taskdef.Actions.Item(1).Arguments = $env:_args\r\n');
|
||||
child.stdin.write('$tsfolder.RegisterTaskDefinition($task.Name, $taskdef, 4, $null, $null, $null)\r\n');
|
||||
|
||||
child.stdin.write('SCHTASKS /RUN /TN MeshChatTask\r\n');
|
||||
child.stdin.write('SCHTASKS /DELETE /F /TN MeshChatTask\r\nexit\r\n');
|
||||
child.waitExit();
|
||||
}
|
||||
break;
|
||||
case 'linux':
|
||||
child = require('child_process').execFile('/usr/bin/xdg-open', ['xdg-open', url], { uid: require('user-sessions').consoleUid() });
|
||||
|
@ -299,7 +299,9 @@
|
||||
"titlePicture": { "type": "string", "default": null, "description": "Web site .png logo file that is 450x66 in size placed in meshcentral-data that is used on the top of many pages." },
|
||||
"loginPicture": { "type": "string", "default": null, "description": "Web site .png logo file placed in meshcentral-data that used on the login page when sitestyle is 2." },
|
||||
"rootRedirect": { "type": "string", "default": null, "description": "Redirects HTTP root requests to this URL. When in use, direct users to /login to see the normal login page." },
|
||||
"mobileSite": { "type": "boolean", "default": true, "description": "When set to false, this setting will disable the mobile site." },
|
||||
"unknownUserRootRedirect": { "type": "string", "default": null, "description": "Redirects HTTP root requests to this URL only where user is not already logged in. When in use, direct users to /login to see the normal login page." },
|
||||
"nightMode": { "type": "integer", "default": 0, "description": "0 = User selects day/night mode, 1 = Always night mode, 2 = Always day mode" },
|
||||
"userQuota": { "type": "integer" },
|
||||
"meshQuota": { "type": "integer" },
|
||||
"loginKey": { "type": [ "string", "array" ], "items": { "type": "string" }, "default": null, "description": "Requires that users add the value ?key=xxx in the URL in order to see the web site." },
|
||||
@ -442,6 +444,8 @@
|
||||
"sms2factor": { "type": "boolean", "default": true, "description": "Set to false to disable SMS 2FA." },
|
||||
"push2factor": { "type": "boolean", "default": true, "description": "Set to false to disable push notification 2FA." },
|
||||
"otp2factor": { "type": "boolean", "default": true, "description": "Set to false to disable one-time-password 2FA." },
|
||||
"backupcode2factor": { "type": "boolean", "default": true, "description": "Set to false to disable 2FA backup codes." },
|
||||
"single2factorWarning": { "type": "boolean", "default": true, "description": "Set to false to disable single 2FA warning." },
|
||||
"lock2factor": { "type": "boolean", "default": false, "description": "When set to true, prevents any changes to 2FA." },
|
||||
"force2factor": { "type": "boolean", "default": false, "description": "Requires that all accounts setup 2FA." },
|
||||
"skip2factor": { "type": "string", "description": "IP addresses where 2FA login is skipped, for example: 127.0.0.1,192.168.2.0/24" },
|
||||
@ -450,7 +454,8 @@
|
||||
"loginTokens": { "type": "boolean", "default": true, "description": "Allows users to create alternative username/passwords for their account." },
|
||||
"twoFactorTimeout": { "type": "integer", "default": 300, "description": "Maximum about of time the to wait for a 2FA token on the login page in seconds." },
|
||||
"autofido2fa": { "type": "boolean", "default": false, "description": "If true and user account has FIDO key setup, 2FA login screen will automatically request FIDO 2FA." },
|
||||
"maxfidokeys": { "type": "integer", "default": null, "description": "Maximum number of FIDO/YubikeyOTP hardware 2FA keys that can be setup in a user account." }
|
||||
"maxfidokeys": { "type": "integer", "default": null, "description": "Maximum number of FIDO/YubikeyOTP hardware 2FA keys that can be setup in a user account." },
|
||||
"allowaccountreset": { "type": "boolean", "default": true, "description": "If set to false, the account reset option on the login screen will not be available to users." }
|
||||
}
|
||||
},
|
||||
"twoFactorCookieDurationDays": { "type": "integer", "default": 30, "description": "Number of days that a user is allowed to remember this device for when completing 2FA. Set this to 0 to remove this option." },
|
||||
@ -510,6 +515,7 @@
|
||||
"description": { "type": "string", "default": "Mesh Agent background service", "description": "The description of the agent as displayed to the user." },
|
||||
"companyName": { "type": "string", "default": "Mesh Agent", "description": "This will be used as the path to install the agent, by default this is 'Mesh Agent' in Windows and 'meshagent' in other OS's." },
|
||||
"serviceName": { "type": "string", "default": "Mesh Agent", "description": "The name of the background service, by default this is 'Mesh Agent' in Windows and 'meshagent' in other OS's but should be set to an all lower case, no space string." },
|
||||
"installText": { "type": "string", "default": null, "description": "Text string to show in the agent installation dialog box." },
|
||||
"image": { "type": "string", "default": null, "description": "The filename of a image file in .png format located in meshcentral-data to display in the MeshCentral Agent installation dialog, image should be square and from 64x64 to 200x200." },
|
||||
"fileName": { "type": "string", "default": "meshagent", "description": "The agent filename." }
|
||||
}
|
||||
|
102
meshcentral.js
102
meshcentral.js
@ -17,7 +17,7 @@
|
||||
const common = require('./common.js');
|
||||
|
||||
// If app metrics is available
|
||||
if (process.argv[2] == '--launch') { try { require('appmetrics-dash').monitor({ url: '/', title: 'MeshCentral', port: 88, host: '127.0.0.1' }); } catch (e) { } }
|
||||
if (process.argv[2] == '--launch') { try { require('appmetrics-dash').monitor({ url: '/', title: 'MeshCentral', port: 88, host: '127.0.0.1' }); } catch (ex) { } }
|
||||
|
||||
function CreateMeshCentralServer(config, args) {
|
||||
var obj = {};
|
||||
@ -76,7 +76,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
|
||||
// Server version
|
||||
obj.currentVer = null;
|
||||
function getCurrentVersion() { try { obj.currentVer = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'package.json'), 'utf8')).version; } catch (e) { } return obj.currentVer; } // Fetch server version
|
||||
function getCurrentVersion() { try { obj.currentVer = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'package.json'), 'utf8')).version; } catch (ex) { } return obj.currentVer; } // Fetch server version
|
||||
getCurrentVersion();
|
||||
|
||||
// Setup the default configuration and files paths
|
||||
@ -118,8 +118,8 @@ function CreateMeshCentralServer(config, args) {
|
||||
if (obj.config.settings && (typeof obj.config.settings.filespath == 'string')) { obj.filespath = obj.config.settings.filespath; }
|
||||
|
||||
// Create data and files folders if needed
|
||||
try { obj.fs.mkdirSync(obj.datapath); } catch (e) { }
|
||||
try { obj.fs.mkdirSync(obj.filespath); } catch (e) { }
|
||||
try { obj.fs.mkdirSync(obj.datapath); } catch (ex) { }
|
||||
try { obj.fs.mkdirSync(obj.filespath); } catch (ex) { }
|
||||
|
||||
// Windows Specific Code, setup service and event log
|
||||
obj.service = null;
|
||||
@ -134,10 +134,10 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Start the Meshcentral server
|
||||
obj.Start = function () {
|
||||
var i;
|
||||
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.
|
||||
try { require('./pass').hash('test', function () { }, 0); } catch (ex) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
||||
|
||||
// Check for invalid arguments
|
||||
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', 'removesubdomain', 'adminaccount', 'domain', 'email', 'configfile', 'maintenancemode', 'nedbtodb', 'removetestagents', 'agentupdatetest', 'hashpassword', 'hashpass', 'indexmcrec', 'mpsdebug'];
|
||||
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', 'removesubdomain', 'adminaccount', 'domain', 'email', 'configfile', 'maintenancemode', 'nedbtodb', 'removetestagents', 'agentupdatetest', 'hashpassword', 'hashpass', 'indexmcrec', 'mpsdebug', 'dumpcores'];
|
||||
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.
|
||||
@ -173,7 +173,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Fix a NeDB database
|
||||
if (obj.args.dbfix) {
|
||||
var lines = null, badJsonCount = 0, feildNames = [], fixedDb = [];
|
||||
try { lines = obj.fs.readFileSync(obj.getConfigFilePath(obj.args.dbfix), { encoding: 'utf8' }).split('\n'); } catch (e) { console.log('Invalid file: ' + obj.args.dbfix + ': ' + e); process.exit(); }
|
||||
try { lines = obj.fs.readFileSync(obj.getConfigFilePath(obj.args.dbfix), { encoding: 'utf8' }).split('\n'); } catch (ex) { console.log('Invalid file: ' + obj.args.dbfix + ': ' + ex); process.exit(); }
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var x = null;
|
||||
try { x = JSON.parse(lines[i]); } catch (ex) { badJsonCount++; }
|
||||
@ -190,6 +190,9 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Perform a password hash
|
||||
if (obj.args.hashpassword) { require('./pass').hash(obj.args.hashpassword, function (err, salt, hash, tag) { console.log(salt + ',' + hash); process.exit(); }); return; }
|
||||
|
||||
// Dump to mesh cores
|
||||
if (obj.args.dumpcores) { obj.updateMeshCore(function () { console.log('Done.'); }, true); return; }
|
||||
|
||||
// Perform web site translations into different languages
|
||||
if (obj.args.translate) {
|
||||
// Check NodeJS version
|
||||
@ -381,10 +384,10 @@ function CreateMeshCentralServer(config, args) {
|
||||
svc.on('alreadyinstalled', function () { console.log('MeshCentral service already installed.'); process.exit(); });
|
||||
svc.on('invalidinstallation', function () { console.log('Invalid MeshCentral service installation.'); process.exit(); });
|
||||
|
||||
if (obj.args.xinstall == true) { try { svc.install(); } catch (e) { logException(e); } }
|
||||
if (obj.args.stop == true || obj.args.restart == true) { try { svc.stop(); } catch (e) { logException(e); } }
|
||||
if (obj.args.start == true) { try { svc.start(); } catch (e) { logException(e); } }
|
||||
if (obj.args.xuninstall == true) { try { svc.uninstall(); } catch (e) { logException(e); } }
|
||||
if (obj.args.xinstall == true) { try { svc.install(); } catch (ex) { logException(ex); } }
|
||||
if (obj.args.stop == true || obj.args.restart == true) { try { svc.stop(); } catch (ex) { logException(ex); } }
|
||||
if (obj.args.start == true) { try { svc.start(); } catch (ex) { logException(ex); } }
|
||||
if (obj.args.xuninstall == true) { try { svc.uninstall(); } catch (ex) { logException(ex); } }
|
||||
return;
|
||||
}
|
||||
|
||||
@ -534,7 +537,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
xxprocess.stderr.on('data', function (data) { });
|
||||
xxprocess.on('close', function (code) {
|
||||
var latestVer = null;
|
||||
if (code == 0) { try { latestVer = xxprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
|
||||
if (code == 0) { try { latestVer = xxprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (ex) { } }
|
||||
callback(getCurrentVersion(), latestVer);
|
||||
});
|
||||
} catch (ex) { callback(getCurrentVersion(), null, ex); } // If the system is running out of memory, an exception here can easily happen.
|
||||
@ -560,7 +563,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
try {
|
||||
var lines = xxprocess.data.split('\r\n').join('\n').split('\n');
|
||||
for (var i in lines) { var s = lines[i].split(': '); if ((s.length == 2) && (obj.args.npmtag == null) || (obj.args.npmtag == s[0])) { tags[s[0]] = s[1]; } }
|
||||
} catch (e) { }
|
||||
} catch (ex) { }
|
||||
}
|
||||
callback(tags);
|
||||
});
|
||||
@ -1045,10 +1048,10 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Import the entire database from a JSON file
|
||||
if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); }
|
||||
var json = null, json2 = '', badCharCount = 0;
|
||||
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
||||
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (ex) { console.log('Invalid JSON file: ' + obj.args.dbimport + ': ' + ex); process.exit(); }
|
||||
for (i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
||||
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
||||
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
||||
try { json = JSON.parse(json2); } catch (ex) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
||||
if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); }
|
||||
// Escape MongoDB invalid field chars
|
||||
for (i in json) {
|
||||
@ -1086,10 +1089,10 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Import the entire database from a JSON file
|
||||
if (obj.args.dbmerge == true) { obj.args.dbmerge = obj.getConfigFilePath('meshcentral.db.json'); }
|
||||
var json = null, json2 = "", badCharCount = 0;
|
||||
try { json = obj.fs.readFileSync(obj.args.dbmerge, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbmerge + ': ' + e); process.exit(); }
|
||||
try { json = obj.fs.readFileSync(obj.args.dbmerge, { encoding: 'utf8' }); } catch (ex) { console.log('Invalid JSON file: ' + obj.args.dbmerge + ': ' + ex); process.exit(); }
|
||||
for (i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
||||
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
||||
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbmerge + ': ' + e); process.exit(); }
|
||||
try { json = JSON.parse(json2); } catch (ex) { console.log('Invalid JSON format: ' + obj.args.dbmerge + ': ' + ex); process.exit(); }
|
||||
if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); }
|
||||
|
||||
// Get all users from current database
|
||||
@ -1556,7 +1559,17 @@ function CreateMeshCentralServer(config, args) {
|
||||
var translations = JSON.parse(obj.fs.readFileSync(translationpath).toString());
|
||||
if (translations['zh-chs']) { translations['zh-hans'] = translations['zh-chs']; delete translations['zh-chs']; }
|
||||
if (translations['zh-cht']) { translations['zh-hant'] = translations['zh-cht']; delete translations['zh-cht']; }
|
||||
obj.agentTranslations = JSON.stringify(translations);
|
||||
|
||||
// If there is domain customizations to the agent strings, do this here.
|
||||
for (var i in obj.config.domains) {
|
||||
var domainTranslations = translations;
|
||||
if ((typeof obj.config.domains[i].agentcustomization == 'object') && (typeof obj.config.domains[i].agentcustomization.installtext == 'string')) {
|
||||
domainTranslations = Object.assign({}, domainTranslations); // Shallow clone
|
||||
for (var j in domainTranslations) { delete domainTranslations[j].description; }
|
||||
domainTranslations.en.description = obj.config.domains[i].agentcustomization.installtext;
|
||||
}
|
||||
obj.config.domains[i].agentTranslations = JSON.stringify(domainTranslations);
|
||||
}
|
||||
} catch (ex) { }
|
||||
|
||||
// Load the list of mesh agents and install scripts
|
||||
@ -2428,7 +2441,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
}
|
||||
|
||||
// Update the default mesh core
|
||||
obj.updateMeshCore = function (func) {
|
||||
obj.updateMeshCore = function (func, dumpToFile) {
|
||||
// Figure out where meshcore.js is
|
||||
var meshcorePath = obj.datapath;
|
||||
if (obj.fs.existsSync(obj.path.join(meshcorePath, 'meshcore.js')) == false) {
|
||||
@ -2476,12 +2489,12 @@ function CreateMeshCentralServer(config, args) {
|
||||
}
|
||||
}
|
||||
|
||||
if (obj.args.minifycore !== false) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.min.js')).toString(); } catch (e) { } } // Favor minified meshcore if present.
|
||||
if (meshCore == null) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.js')).toString(); } catch (e) { } } // Use non-minified meshcore.
|
||||
if (obj.args.minifycore !== false) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.min.js')).toString(); } catch (ex) { } } // Favor minified meshcore if present.
|
||||
if (meshCore == null) { try { meshCore = obj.fs.readFileSync(obj.path.join(meshcorePath, 'meshcore.js')).toString(); } catch (ex) { } } // Use non-minified meshcore.
|
||||
if (meshCore != null) {
|
||||
var moduleDirPath = null;
|
||||
if (obj.args.minifycore !== false) { try { moduleDirPath = obj.path.join(meshcorePath, 'modules_meshcore_min'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (e) { } } // Favor minified modules if present.
|
||||
if (modulesDir == null) { try { moduleDirPath = obj.path.join(meshcorePath, 'modules_meshcore'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (e) { } } // Use non-minified mofules.
|
||||
if (obj.args.minifycore !== false) { try { moduleDirPath = obj.path.join(meshcorePath, 'modules_meshcore_min'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (ex) { } } // Favor minified modules if present.
|
||||
if (modulesDir == null) { try { moduleDirPath = obj.path.join(meshcorePath, 'modules_meshcore'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (ex) { } } // Use non-minified mofules.
|
||||
if (modulesDir != null) {
|
||||
for (var i in modulesDir) {
|
||||
if (modulesDir[i].toLowerCase().endsWith('.json')) {
|
||||
@ -2500,7 +2513,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
// We are adding a JS file to the meshcores
|
||||
var moduleName = modulesDir[i].substring(0, modulesDir[i].length - 3);
|
||||
if (moduleName.endsWith('.min')) { moduleName = moduleName.substring(0, moduleName.length - 4); } // Remove the ".min" for ".min.js" files.
|
||||
const moduleData = [ 'try { addModule("', moduleName, '", "', obj.escapeCodeString(obj.fs.readFileSync(obj.path.join(moduleDirPath, modulesDir[i])).toString('binary')), '"); addedModules.push("', moduleName, '"); } catch (e) { }\r\n' ];
|
||||
const moduleData = [ 'try { addModule("', moduleName, '", "', obj.escapeCodeString(obj.fs.readFileSync(obj.path.join(moduleDirPath, modulesDir[i])).toString('binary')), '"); addedModules.push("', moduleName, '"); } catch (ex) { }\r\n' ];
|
||||
|
||||
// Merge this module
|
||||
// NOTE: "smbios" module makes some non-AI Linux segfault, only include for IA platforms.
|
||||
@ -2542,6 +2555,9 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Add plugins to cores
|
||||
if (obj.pluginHandler) { obj.pluginHandler.addMeshCoreModules(modulesAdd); }
|
||||
|
||||
// If we need to dump modules to file, create a meshcores folder
|
||||
if (dumpToFile) { try { obj.fs.mkdirSync('meshcores'); } catch (ex) { } }
|
||||
|
||||
// Merge the cores and compute the hashes
|
||||
for (var i in modulesAdd) {
|
||||
if ((i == 'windows-recovery') || (i == 'linux-recovery')) {
|
||||
@ -2557,9 +2573,11 @@ function CreateMeshCentralServer(config, args) {
|
||||
obj.defaultMeshCoresHash[i] = obj.crypto.createHash('sha384').update(obj.defaultMeshCores[i]).digest('binary');
|
||||
obj.debug('main', 'Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes.');
|
||||
|
||||
// These lines will write all modules to files. Great for debugging.
|
||||
//console.log('Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes.'); // DEBUG, Print the core size
|
||||
//obj.fs.writeFile("C:\\temp\\" + i + ".js", obj.defaultMeshCores[i].slice(4), function () { }); // DEBUG, Write the core to file
|
||||
// Write all modules to files. Great for debugging.
|
||||
if (dumpToFile) {
|
||||
console.log('Core module ' + i + ' is ' + obj.defaultMeshCores[i].length + ' bytes, saving to meshcores/' + i + '.js.'); // Print the core size and filename
|
||||
obj.fs.writeFile('meshcores/' + i + '.js', obj.defaultMeshCores[i].slice(4), function () { }); // Write the core to file
|
||||
}
|
||||
|
||||
// Compress the mesh cores with DEFLATE
|
||||
const callback = function MeshCoreDeflateCb(err, buffer) { if (err == null) { obj.defaultMeshCoresDeflate[MeshCoreDeflateCb.i] = buffer; } }
|
||||
@ -2585,10 +2603,10 @@ function CreateMeshCentralServer(config, args) {
|
||||
meshCmd = meshCmd.replace("'***Mesh*Cmd*Version***'", '\'' + getCurrentVersion() + '\'');
|
||||
|
||||
// Figure out where the modules_meshcmd folder is.
|
||||
if (obj.args.minifycore !== false) { try { moduleDirPath = obj.path.join(meshcmdPath, 'modules_meshcmd_min'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (e) { } } // Favor minified modules if present.
|
||||
if (modulesDir == null) { try { moduleDirPath = obj.path.join(meshcmdPath, 'modules_meshcmd'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (e) { } } // Use non-minified mofules.
|
||||
if (obj.args.minifycore !== false) { if (modulesDir == null) { try { moduleDirPath = obj.path.join(__dirname, 'agents', 'modules_meshcmd_min'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (e) { } } } // Favor minified modules if present.
|
||||
if (modulesDir == null) { try { moduleDirPath = obj.path.join(__dirname, 'agents', 'modules_meshcmd'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (e) { } } // Use non-minified mofules.
|
||||
if (obj.args.minifycore !== false) { try { moduleDirPath = obj.path.join(meshcmdPath, 'modules_meshcmd_min'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (ex) { } } // Favor minified modules if present.
|
||||
if (modulesDir == null) { try { moduleDirPath = obj.path.join(meshcmdPath, 'modules_meshcmd'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (ex) { } } // Use non-minified mofules.
|
||||
if (obj.args.minifycore !== false) { if (modulesDir == null) { try { moduleDirPath = obj.path.join(__dirname, 'agents', 'modules_meshcmd_min'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (ex) { } } } // Favor minified modules if present.
|
||||
if (modulesDir == null) { try { moduleDirPath = obj.path.join(__dirname, 'agents', 'modules_meshcmd'); modulesDir = obj.fs.readdirSync(moduleDirPath); } catch (ex) { } } // Use non-minified mofules.
|
||||
|
||||
// Read all .js files in the meshcmd modules folder.
|
||||
if (modulesDir != null) {
|
||||
@ -2597,7 +2615,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Merge this module
|
||||
var moduleName = modulesDir[i].substring(0, modulesDir[i].length - 3);
|
||||
if (moduleName.endsWith('.min')) { moduleName = moduleName.substring(0, moduleName.length - 4); } // Remove the ".min" for ".min.js" files.
|
||||
moduleAdditions.push('try { addModule("', moduleName, '", "', obj.escapeCodeString(obj.fs.readFileSync(obj.path.join(moduleDirPath, modulesDir[i])).toString('binary')), '"); addedModules.push("', moduleName, '"); } catch (e) { }\r\n');
|
||||
moduleAdditions.push('try { addModule("', moduleName, '", "', obj.escapeCodeString(obj.fs.readFileSync(obj.path.join(moduleDirPath, modulesDir[i])).toString('binary')), '"); addedModules.push("', moduleName, '"); } catch (ex) { }\r\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2643,7 +2661,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
obj.meshToolsBinaries[this.toolname] = { hash: data.toString('hex'), hashx: this.hashx, path: this.toolpath, dlname: this.dlname, url: this.url };
|
||||
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.toolpath); } catch (e) { }
|
||||
try { stats = obj.fs.statSync(this.toolpath); } catch (ex) { }
|
||||
if (stats != null) { obj.meshToolsBinaries[this.toolname].size = stats.size; }
|
||||
});
|
||||
var options = { sourcePath: toolpath, targetStream: hashStream };
|
||||
@ -2670,7 +2688,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
obj.meshToolsBinaries[this.toolname].dlname = 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) { }
|
||||
try { stats = obj.fs.statSync(this.agentpath); } catch (ex) { }
|
||||
if (stats != null) { obj.meshToolsBinaries[this.toolname].size = stats.size; }
|
||||
});
|
||||
stream.toolname = toolname;
|
||||
@ -2678,7 +2696,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
stream.dlname = meshToolsList[toolname].dlname;
|
||||
stream.hash = obj.crypto.createHash('sha384', stream);
|
||||
stream.hashx = 0;
|
||||
} catch (e) { }
|
||||
} catch (ex) { }
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -2712,7 +2730,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
obj.meshAgentInstallScripts[this.info.id].data = this.xdata;
|
||||
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) { }
|
||||
try { stats = obj.fs.statSync(this.agentpath); } catch (ex) { }
|
||||
if (stats != null) { obj.meshAgentInstallScripts[this.info.id].size = stats.size; }
|
||||
|
||||
// Place Unit line breaks on Linux scripts if not already present.
|
||||
@ -2721,7 +2739,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
stream.info = meshAgentsInstallScriptList[scriptid];
|
||||
stream.agentpath = scriptpath;
|
||||
stream.hash = obj.crypto.createHash('sha384', stream);
|
||||
} catch (e) { }
|
||||
} catch (ex) { }
|
||||
}
|
||||
};
|
||||
|
||||
@ -2786,7 +2804,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
|
||||
// Fetch all the agent binary information
|
||||
var stats = null;
|
||||
try { stats = obj.fs.statSync(agentpath); } catch (e) { }
|
||||
try { stats = obj.fs.statSync(agentpath); } catch (ex) { }
|
||||
if ((stats != null)) {
|
||||
// If file exists
|
||||
archcount++;
|
||||
@ -2798,7 +2816,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
|
||||
// If this is a windows binary, pull binary information
|
||||
if (obj.meshAgentsArchitectureNumbers[archid].platform == 'win32') {
|
||||
try { obj.meshAgentBinaries[archid].pe = obj.exeHandler.parseWindowsExecutable(agentpath); } catch (e) { }
|
||||
try { obj.meshAgentBinaries[archid].pe = obj.exeHandler.parseWindowsExecutable(agentpath); } catch (ex) { }
|
||||
}
|
||||
|
||||
// If agents must be stored in RAM or if this is a Windows 32/64 agent, load the agent in RAM.
|
||||
@ -3235,7 +3253,7 @@ function getConfig(createSampleConfig) {
|
||||
datapath = path.join(__dirname, '../meshcentral-data');
|
||||
}
|
||||
if (args.datapath) { datapath = args.datapath; }
|
||||
try { fs.mkdirSync(datapath); } catch (e) { }
|
||||
try { fs.mkdirSync(datapath); } catch (ex) { }
|
||||
|
||||
// Read configuration file if present and change arguments.
|
||||
var config = {}, configFilePath = path.join(datapath, 'config.json');
|
||||
@ -3244,7 +3262,7 @@ function getConfig(createSampleConfig) {
|
||||
}
|
||||
if (fs.existsSync(configFilePath)) {
|
||||
// Load and validate the configuration file
|
||||
try { config = require(configFilePath); } catch (e) { console.log('ERROR: Unable to parse ' + configFilePath + '.'); return null; }
|
||||
try { config = require(configFilePath); } catch (ex) { console.log('ERROR: Unable to parse ' + configFilePath + '.'); return null; }
|
||||
if (config.domains == null) { config.domains = {}; }
|
||||
for (i in config.domains) { if ((i.split('/').length > 1) || (i.split(' ').length > 1)) { console.log("ERROR: Error in config.json, domain names can't have spaces or /."); return null; } }
|
||||
} else {
|
||||
@ -3292,7 +3310,7 @@ function InstallModules(modules, func) {
|
||||
if (typeof dependencies[moduleName] != undefined) { moduleVersion = dependencies[moduleName]; }
|
||||
require(moduleName);
|
||||
}
|
||||
} catch (e) {
|
||||
} catch (ex) {
|
||||
if (previouslyInstalledModules[modules[i]] !== true) { missingModules.push(moduleNameAndVersion); }
|
||||
}
|
||||
}
|
||||
|
@ -58,10 +58,11 @@ MNG_ENCAPSULATE_AGENT_COMMAND = 70,
|
||||
MNG_KVM_DISPLAY_INFO = 82
|
||||
*/
|
||||
|
||||
function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
|
||||
function CreateDesktopMultiplexor(parent, domain, nodeid, id, func) {
|
||||
var obj = {};
|
||||
obj.nodeid = nodeid;
|
||||
obj.parent = parent;
|
||||
obj.id = id; // Unique identifier for this session
|
||||
obj.nodeid = nodeid; // Remote device nodeid for this session
|
||||
obj.parent = parent; // Parent web server instance
|
||||
obj.agent = null; // Reference to the connection object that is the agent.
|
||||
obj.viewers = []; // Array of references to all viewers.
|
||||
obj.viewersOverflowCount = 0; // Number of viewers currently in overflow state.
|
||||
@ -180,7 +181,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
|
||||
|
||||
// Log joining the multiplex session
|
||||
if (obj.startTime != null) {
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user ? peer.user._id : null, username: peer.user.name, msgid: 4, msg: "Joined desktop multiplex session", protocol: 2 };
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user ? peer.user._id : null, username: peer.user.name, msgid: 143, msgArgs: [obj.id], msg: "Joined desktop multiplex session \"" + obj.id + "\"", protocol: 2 };
|
||||
parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id, obj.meshid], obj, event);
|
||||
}
|
||||
|
||||
@ -208,7 +209,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
|
||||
|
||||
// Log multiplex session start
|
||||
if ((obj.agent != null) && (obj.viewers.length > 0) && (obj.startTime == null)) {
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msgid: 6, msg: "Started desktop multiplex session", protocol: 2 };
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msgid: 145, msgArgs: [obj.id], msg: "Started desktop multiplex session \"" + obj.id + "\"", protocol: 2 };
|
||||
if (obj.viewers[0].user != null) { event.userid = obj.viewers[0].user._id; event.username = obj.viewers[0].user.name; }
|
||||
const targets = ['*', obj.nodeid, obj.meshid];
|
||||
if (obj.viewers[0].user != null) { targets.push(obj.viewers[0].user._id); }
|
||||
@ -288,7 +289,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
|
||||
|
||||
//var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msgid: 5, msg: "Left the desktop multiplex session", protocol: 2 };
|
||||
const sessionSeconds = Math.floor((Date.now() - peer.startTime) / 1000);
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msgid: 122, msgArgs: [sessionSeconds], msg: "Left the desktop multiplex session after " + sessionSeconds + " second(s).", protocol: 2, bytesin: inTraffc, bytesout: outTraffc };
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msgid: 144, msgArgs: [obj.id, sessionSeconds], msg: "Left the desktop multiplex session \"" + obj.id + "\" after " + sessionSeconds + " second(s).", protocol: 2, bytesin: inTraffc, bytesout: outTraffc };
|
||||
if (peer.user != null) { event.userid = peer.user._id; event.username = peer.user.name; }
|
||||
if (peer.guestName) { event.guestname = peer.guestName; }
|
||||
const targets = ['*', obj.nodeid, obj.meshid];
|
||||
@ -342,7 +343,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
|
||||
|
||||
// Add a event entry about this recording
|
||||
var basefile = parent.parent.path.basename(filename);
|
||||
var event = { etype: 'relay', action: 'recording', domain: domain.id, nodeid: obj.nodeid, msgid: 7, msgArgs: [obj.sessionLength], msg: "Finished recording session" + (obj.sessionLength ? (', ' + obj.sessionLength + ' second(s)') : ''), filename: basefile, size: obj.recordingFileSize, protocol: 2, icon: obj.icon, name: obj.name, meshid: obj.meshid, userids: obj.userIds, multiplex: true };
|
||||
var event = { etype: 'relay', action: 'recording', domain: domain.id, nodeid: obj.nodeid, msgid: 146, msgArgs: [obj.id, obj.sessionLength], msg: "Finished recording session \"" + obj.id + "\", " + obj.sessionLength + " second(s)", filename: basefile, size: obj.recordingFileSize, protocol: 2, icon: obj.icon, name: obj.name, meshid: obj.meshid, userids: obj.userIds, multiplex: true };
|
||||
var mesh = parent.meshes[obj.meshid];
|
||||
if (mesh != null) { event.meshname = mesh.name; }
|
||||
if (obj.sessionStart) { event.startTime = obj.sessionStart; event.lengthTime = obj.sessionLength; }
|
||||
@ -354,7 +355,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
|
||||
|
||||
// Log end of multiplex session
|
||||
if (obj.startTime != null) {
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msgid: 8, msgArgs: [Math.floor((Date.now() - obj.startTime) / 1000)], msg: "Closed desktop multiplex session" + ', ' + Math.floor((Date.now() - obj.startTime) / 1000) + ' second(s)', protocol: 2 };
|
||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, msgid: 147, msgArgs: [obj.id, Math.floor((Date.now() - obj.startTime) / 1000)], msg: "Closed desktop multiplex session \"" + obj.id + "\", " + Math.floor((Date.now() - obj.startTime) / 1000) + ' second(s)', protocol: 2 };
|
||||
parent.parent.DispatchEvent(['*', obj.nodeid, obj.meshid], obj, event);
|
||||
obj.startTime = null;
|
||||
}
|
||||
@ -1203,7 +1204,7 @@ function CreateMeshRelayEx2(parent, ws, req, domain, user, cookie) {
|
||||
if (obj.deskMultiplexor == null) {
|
||||
parent.desktoprelays[obj.nodeid] = 1; // Indicate that the creating of the desktop multiplexor is pending.
|
||||
parent.parent.debug('relay', 'DesktopRelay: Creating new desktop multiplexor');
|
||||
CreateDesktopMultiplexor(parent, domain, obj.nodeid, function (deskMultiplexor) {
|
||||
CreateDesktopMultiplexor(parent, domain, obj.nodeid, obj.id, function (deskMultiplexor) {
|
||||
if (deskMultiplexor != null) {
|
||||
// Desktop multiplexor was created, use it.
|
||||
obj.deskMultiplexor = deskMultiplexor;
|
||||
|
35
meshuser.js
35
meshuser.js
@ -3183,6 +3183,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Do not allow this command if 2FA's are locked
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.lock2factor == true)) return;
|
||||
|
||||
// Do not allow this command if backup codes are not allowed
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.backupcode2factor == false)) return;
|
||||
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
@ -3211,6 +3214,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Do not allow this command if 2FA's are locked
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.lock2factor == true)) return;
|
||||
|
||||
// Do not allow this command if backup codes are not allowed
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.backupcode2factor == false)) return;
|
||||
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
@ -3250,6 +3256,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Do not allow this command if 2FA's are locked
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.lock2factor == true)) return;
|
||||
|
||||
// Do not allow this command if backup codes are not allowed
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.backupcode2factor == false)) return;
|
||||
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
@ -3281,6 +3290,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Do not allow this command if 2FA's are locked
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.lock2factor == true)) return;
|
||||
|
||||
// Do not allow this command if backup codes are not allowed
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.backupcode2factor == false)) return;
|
||||
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
@ -4571,7 +4583,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (type == 'csv') {
|
||||
try {
|
||||
// Create the CSV file
|
||||
output = 'id,name,rname,host,icon,ip,osdesc,groupname,av,update,firewall,avdetails,cpu,osbuild,biosDate,biosVendor,biosVersion,boardName,boardVendor,boardVersion,productUuid,agentOpenSSL,agentCommitDate,agentCommitHash,agentCompileTime,netIfCount,macs,addresses,lastConnectTime,lastConnectAddr\r\n';
|
||||
output = 'id,name,rname,host,icon,ip,osdesc,groupname,av,update,firewall,avdetails,cpu,osbuild,biosDate,biosVendor,biosVersion,boardName,boardVendor,boardVersion,productUuid,totalMemory,agentOpenSSL,agentCommitDate,agentCommitHash,agentCompileTime,netIfCount,macs,addresses,lastConnectTime,lastConnectAddr\r\n';
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
const nodeinfo = results[i];
|
||||
|
||||
@ -4613,6 +4625,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (nodeinfo.sys.hardware.identifiers && (nodeinfo.sys.hardware.identifiers.board_version)) { output += csvClean(nodeinfo.sys.hardware.identifiers.board_version); }
|
||||
output += ',';
|
||||
if (nodeinfo.sys.hardware.identifiers && (nodeinfo.sys.hardware.identifiers.product_uuid)) { output += csvClean(nodeinfo.sys.hardware.identifiers.product_uuid); }
|
||||
output += ',';
|
||||
if (nodeinfo.sys.hardware.windows.memory) {
|
||||
var totalMemory = 0;
|
||||
for (var j in nodeinfo.sys.hardware.windows.memory) {
|
||||
if (nodeinfo.sys.hardware.windows.memory[j].Capacity) {
|
||||
if (typeof nodeinfo.sys.hardware.windows.memory[j].Capacity == 'number') { totalMemory += nodeinfo.sys.hardware.windows.memory[j].Capacity; }
|
||||
if (typeof nodeinfo.sys.hardware.windows.memory[j].Capacity == 'string') { totalMemory += parseInt(nodeinfo.sys.hardware.windows.memory[j].Capacity); }
|
||||
}
|
||||
}
|
||||
output += csvClean('' + totalMemory);
|
||||
}
|
||||
} else if ((nodeinfo.sys) && (nodeinfo.sys.hardware) && (nodeinfo.sys.hardware.mobile)) {
|
||||
// Mobile
|
||||
output += ',';
|
||||
@ -4628,6 +4651,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
output += ',';
|
||||
output += ',';
|
||||
if (nodeinfo.sys.hardware.mobile && (nodeinfo.sys.hardware.mobile.id)) { output += csvClean(nodeinfo.sys.hardware.mobile.id); }
|
||||
output += ',';
|
||||
} else if ((nodeinfo.sys) && (nodeinfo.sys.hardware) && (nodeinfo.sys.hardware.windows) && (nodeinfo.sys.hardware.linux)) {
|
||||
// Linux
|
||||
output += ',';
|
||||
@ -4646,8 +4670,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (nodeinfo.sys.hardware.linux && (nodeinfo.sys.hardware.linux.board_version)) { output += csvClean(nodeinfo.sys.hardware.linux.board_version); }
|
||||
output += ',';
|
||||
if (nodeinfo.sys.hardware.linux && (nodeinfo.sys.hardware.linux.product_uuid)) { output += csvClean(nodeinfo.sys.hardware.linux.product_uuid); }
|
||||
output += ',';
|
||||
} else {
|
||||
output += ',,,,,,,,,';
|
||||
output += ',,,,,,,,,,';
|
||||
}
|
||||
|
||||
// Agent information
|
||||
@ -5265,7 +5290,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
// Perform email invitation
|
||||
if ((command.emailInvitation == true) && (command.emailVerified == true) && command.email && domain.mailserver) {
|
||||
domain.mailserver.sendAccountInviteMail(newuserdomain, (user.realname ? user.realname : user.name), newusername, command.email.toLowerCase(), command.pass, parent.getLanguageCodes(req));
|
||||
domain.mailserver.sendAccountInviteMail(newuserdomain, (user.realname ? user.realname : user.name), newusername, command.email.toLowerCase(), command.pass, parent.getLanguageCodes(req), req.query.key);
|
||||
}
|
||||
|
||||
// Log in the auth log
|
||||
@ -5504,7 +5529,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (parent.parent.authlog) { parent.parent.authLog('https', 'User ' + user.name + ' changed email from ' + oldemail + ' to ' + user.email); }
|
||||
|
||||
// Send the verification email
|
||||
if (domain.mailserver != null) { domain.mailserver.sendAccountCheckMail(domain, user.name, user._id, user.email, parent.getLanguageCodes(req)); }
|
||||
if (domain.mailserver != null) { domain.mailserver.sendAccountCheckMail(domain, user.name, user._id, user.email, parent.getLanguageCodes(req), req.query.key); }
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -6100,7 +6125,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
if ((domain.mailserver != null) && (obj.user.email.toLowerCase() == command.email)) {
|
||||
// Send the verification email
|
||||
domain.mailserver.sendAccountCheckMail(domain, user.name, user._id, user.email, parent.getLanguageCodes(req));
|
||||
domain.mailserver.sendAccountCheckMail(domain, user.name, user._id, user.email, parent.getLanguageCodes(req), req.query.key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.9.77",
|
||||
"version": "0.9.79",
|
||||
"keywords": [
|
||||
"Remote Device Management",
|
||||
"Remote Device Monitoring",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -727,7 +727,7 @@
|
||||
<div style="margin-top:5px"><span id="changeEmailId" style="display:none"><a onclick="account_showChangeEmail()" style="cursor:pointer">Change email address</a></span></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showChangePassword()" style="cursor:pointer">Change password</a><span id="p2nextPasswordUpdateTime"></span></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showDeleteAccount()" style="cursor:pointer">Delete account</a></div>
|
||||
<div style="margin-top:5px"><a onclick="toggleNightMode()" style="cursor:pointer">Set dark mode</a></div>
|
||||
<div style="margin-top:5px" id="setDarkModeLink"><a onclick="toggleNightMode()" style="cursor:pointer">Set dark mode</a></div>
|
||||
<div style="margin-top:5px"><a onclick="showNotes(false)" style="cursor:pointer">Personal notes</a></div>
|
||||
</div>
|
||||
<br style=clear:both />
|
||||
@ -1309,6 +1309,9 @@
|
||||
// Session Refresh Timer
|
||||
if (sessionTime >= 10) { sessionRefreshTimer = setTimeout(refreshCookieSession, Math.round((sessionTime * 60000) * 0.8)); }
|
||||
|
||||
// Hide night mode button if needed
|
||||
QV('setDarkModeLink', (features2 & 0x00300000) == 0);
|
||||
|
||||
// Set the user's desktop shortcut keys
|
||||
deskKeyboardShortcuts = [];
|
||||
var deskKeyboardShortcutsStr = getstore('deskKeyShortcuts', '0x0A002E,0x100000,0x100028,0x100026,0x10004C,0x10004D,0x11004D,0x100052,0x020073,0x080057,0x020009,0x100025,0x100027').split(',');
|
||||
@ -1372,7 +1375,7 @@
|
||||
QV('p2AccountImage', !accountSettingsLocked);
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('manageAuthApp', (serverinfo.lock2factor != true) && (features & 4096) && ((userinfo.otpsecret == 1) || ((features2 & 0x00020000) == 0)));
|
||||
QV('manageOtp', (serverinfo.lock2factor != true) && (features & 4096) && ((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0)));
|
||||
QV('manageOtp', (serverinfo.lock2factor != true) && ((features2 & 0x40000) == 0) && (features & 4096) && ((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0)));
|
||||
QV('authPhoneNumberCheck', (userinfo.phone != null));
|
||||
QV('authEmailSetupCheck', (userinfo.otpekey == 1) && (userinfo.email != null) && (userinfo.emailVerified == true));
|
||||
QV('authAppSetupCheck', userinfo.otpsecret == 1);
|
||||
@ -2209,6 +2212,8 @@
|
||||
// Set night mode
|
||||
var nNightMode = getstore('nightMode', '0')
|
||||
nightMode = false;
|
||||
if ((features2 & 0x00100000) != 0) { nNightMode = '1'; }
|
||||
if ((features2 & 0x00200000) != 0) { nNightMode = '2'; }
|
||||
if (nNightMode == '1') { nightMode = true; }
|
||||
else if ((nNightMode == '0') && (window.matchMedia)) { nightMode = window.matchMedia('(prefers-color-scheme: dark)').matches }
|
||||
if (nightMode) { QC('body').add('night'); QS('body')['background-color'] = '#000'; QS('body')['color'] = 'lightgray'; } else { QC('body').remove('night'); QS('body')['background-color'] = '#FFF'; QS('body')['color'] = 'black'; }
|
||||
|
@ -1645,6 +1645,9 @@
|
||||
// Fix links
|
||||
if (urlargs.key) { Q('p6backuplink').href += '?key=' + urlargs.key; }
|
||||
|
||||
// Hide night mode button if needed
|
||||
QV('uiViewButton4', (features2 & 0x00300000) == 0);
|
||||
|
||||
// Fix HTML words that in english have two or more meanings
|
||||
Q('DeskType').value = multiTranslate("[KeyboardTyping]|Type");
|
||||
}
|
||||
@ -1923,6 +1926,8 @@
|
||||
// Set night mode
|
||||
var nNightMode = getstore('nightMode', '0')
|
||||
nightMode = false;
|
||||
if ((features2 & 0x00100000) != 0) { nNightMode = '1'; }
|
||||
if ((features2 & 0x00200000) != 0) { nNightMode = '2'; }
|
||||
if (nNightMode == '1') { nightMode = true; }
|
||||
else if ((nNightMode == '0') && (window.matchMedia)) { nightMode = window.matchMedia('(prefers-color-scheme: dark)').matches }
|
||||
if (nightMode) { QC('body').add('night'); QS('body')['background-color'] = '#000'; } else { QC('body').remove('night'); QS('body')['background-color'] = '#d3d9d6'; }
|
||||
@ -2116,7 +2121,7 @@
|
||||
if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor
|
||||
if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor
|
||||
if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor
|
||||
if ((authFactorCount > 0) && (userinfo.otpkeys > 0)) { authFactorCount++; } // Backup keys
|
||||
if ((authFactorCount > 0) && (userinfo.otpkeys > 0) && ((features & 0x40000) == 0)) { authFactorCount++; } // Backup keys
|
||||
return authFactorCount;
|
||||
}
|
||||
|
||||
@ -2126,7 +2131,7 @@
|
||||
var accountSettingsLocked = ((userinfo.siteadmin != 0xFFFFFFFF) && ((userinfo.siteadmin & 1024) != 0));
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true) && (accountSettingsLocked == false));
|
||||
QV('manageOtp', (serverinfo.lock2factor != true) && (authFactorCount > 0));
|
||||
QV('manageOtp', (serverinfo.lock2factor != true) && (authFactorCount > 0) && ((features2 & 0x40000) == 0));
|
||||
QV('authPhoneNumberCheck', (userinfo.phone != null));
|
||||
QV('authEmailSetupCheck', (userinfo.otpekey == 1) && (userinfo.email != null) && (userinfo.emailVerified == true));
|
||||
QV('authAppSetupCheck', userinfo.otpsecret == 1);
|
||||
@ -2139,7 +2144,7 @@
|
||||
mainUpdate(4 + 128 + 4096);
|
||||
|
||||
// Check if none or at least 2 factors are enabled.
|
||||
if ((backupCodesWarningDone == false) && (authFactorCount == 1)) {
|
||||
if ((backupCodesWarningDone == false) && (authFactorCount == 1) && ((features2 & 0x80000) == 0)) {
|
||||
addNotification({ text: "Please add two-factor backup codes. If the current factor is lost, there is no way to recover this account.", title: "Two factor authentication", tag: 'backupcodes' });
|
||||
backupCodesWarningDone = true;
|
||||
}
|
||||
@ -7411,8 +7416,8 @@
|
||||
var url = serverinfo.altmessenging[i].url.split('{0}').join(currentNode._id.split('/').join('-'));
|
||||
var localurl = url;
|
||||
if (typeof serverinfo.altmessenging[i].localurl == 'string') { localurl = serverinfo.altmessenging[i].localurl.split('{0}').join(currentNode._id.split('/').join('-')); }
|
||||
meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: url });
|
||||
safeNewWindow(localurl, 'altmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560');
|
||||
if (url != '') { meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: url }); }
|
||||
if (localurl != '') { safeNewWindow(localurl, 'altmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560'); }
|
||||
}
|
||||
|
||||
function deviceToggleBackground() {
|
||||
@ -13341,11 +13346,11 @@
|
||||
1: "Account login",
|
||||
2: "Account logout",
|
||||
3: "Changed language from {1} to {2}",
|
||||
4: "Joined desktop multiplex session",
|
||||
5: "Left the desktop multiplex session",
|
||||
6: "Started desktop multiplex session",
|
||||
7: "Finished recording session, {0} second(s)",
|
||||
8: "Closed desktop multiplex session, {0} second(s)",
|
||||
4: "Joined desktop multiplex session", // No longer in use, replaced with 143
|
||||
5: "Left the desktop multiplex session", // No longer in use, replaced with 144
|
||||
6: "Started desktop multiplex session", // No longer in use, replaced with 145
|
||||
7: "Finished recording session, {0} second(s)", // No longer in use, replaced with 146
|
||||
8: "Closed desktop multiplex session, {0} second(s)", // No longer in use, replaced with 147
|
||||
9: "Ended relay session \"{0}\" from {1} to {2}, {3} second(s)",
|
||||
10: "Ended terminal session \"{0}\" from {1} to {2}, {3} second(s)",
|
||||
11: "Ended desktop session \"{0}\" from {1} to {2}, {3} second(s)",
|
||||
@ -13459,7 +13464,7 @@
|
||||
119: "This agent is using insecure tunnels, consider updating.",
|
||||
120: "Started local relay session \"{0}\", protocol {1} to {2}",
|
||||
121: "Ended local relay session \"{0}\", protocol {1} to {2}, {3} second(s)",
|
||||
122: "Left the desktop multiplex session after {0} second(s).",
|
||||
122: "Left the desktop multiplex session after {0} second(s).", // No longer in use, replaced with 144
|
||||
123: "Left Web-SSH session after {0} second(s).",
|
||||
124: "Left Web-SFTP session after {0} second(s).",
|
||||
125: "Left Web-RDP session after {0} second(s).",
|
||||
@ -13479,7 +13484,12 @@
|
||||
139: "Added device share {0} recurring weekly.",
|
||||
140: "Changed device {0} from group {1}: {2}",
|
||||
141: "Intel(r) AMT policy change",
|
||||
142: "Device group {0} was changed: {1}"
|
||||
142: "Device group {0} was changed: {1}",
|
||||
143: "Joined desktop multiplex session \"{0}\"",
|
||||
144: "Left the desktop multiplex session \"{0}\" after {1} second(s).",
|
||||
145: "Started desktop multiplex session \"{0}\"",
|
||||
146: "Finished recording session \"{0}\", {1} second(s)",
|
||||
147: "Closed desktop multiplex session \"{0}\", {1} second(s)"
|
||||
};
|
||||
|
||||
var eventsShortMessageId = {
|
||||
|
28
webserver.js
28
webserver.js
@ -1144,7 +1144,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
}
|
||||
|
||||
// Check if email address needs to be confirmed
|
||||
var emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
const emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
if (emailcheck && (user.emailVerified !== true)) {
|
||||
parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page');
|
||||
req.session.messageid = 3; // "Email verification required" message
|
||||
@ -1165,7 +1165,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
}
|
||||
|
||||
// Check if email address needs to be confirmed
|
||||
var emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
const emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
if (emailcheck && (user.emailVerified !== true)) {
|
||||
parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page');
|
||||
req.session.messageid = 3; // "Email verification required" message
|
||||
@ -1459,7 +1459,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
// Check everything is ok
|
||||
if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap') || (typeof req.body.rpassword1 != 'string') || (typeof req.body.rpassword2 != 'string') || (req.body.rpassword1 != req.body.rpassword2) || (typeof req.body.rpasswordhint != 'string') || (req.session == null) || (typeof req.session.resettokenusername != 'string') || (typeof req.session.resettokenpassword != 'string')) {
|
||||
const allowAccountReset = ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.allowaccountreset !== false));
|
||||
if ((allowAccountReset === false) || (domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap') || (typeof req.body.rpassword1 != 'string') || (typeof req.body.rpassword2 != 'string') || (req.body.rpassword1 != req.body.rpassword2) || (typeof req.body.rpasswordhint != 'string') || (req.session == null) || (typeof req.session.resettokenusername != 'string') || (typeof req.session.resettokenpassword != 'string')) {
|
||||
parent.debug('web', 'handleResetPasswordRequest: checks failed');
|
||||
delete req.session.u2f;
|
||||
delete req.session.loginmode;
|
||||
@ -1568,7 +1569,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
function handleResetAccountRequest(req, res, direct) {
|
||||
const domain = checkUserIpAddress(req, res);
|
||||
if (domain == null) { return; }
|
||||
if ((domain.auth == 'sspi') || (domain.auth == 'ldap') || (obj.args.lanonly == true) || (obj.parent.certificates.CommonName == null) || (obj.parent.certificates.CommonName.indexOf('.') == -1)) { parent.debug('web', 'handleResetAccountRequest: check failed'); res.sendStatus(404); return; }
|
||||
const allowAccountReset = ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.allowaccountreset !== false));
|
||||
if ((allowAccountReset === false) || (domain.auth == 'sspi') || (domain.auth == 'ldap') || (obj.args.lanonly == true) || (obj.parent.certificates.CommonName == null) || (obj.parent.certificates.CommonName.indexOf('.') == -1)) { parent.debug('web', 'handleResetAccountRequest: check failed'); res.sendStatus(404); return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
@ -2883,6 +2885,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
if (domain.devicesearchbarserverandclientname) { features2 += 0x00008000; } // Search bar will find both server name and client name
|
||||
if (domain.ipkvm) { features2 += 0x00010000; } // Indicates support for IP KVM device groups
|
||||
if ((domain.passwordrequirements) && (domain.passwordrequirements.otp2factor == false)) { features2 += 0x00020000; } // Indicates support for OTP 2FA is disabled
|
||||
if ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.backupcode2factor === false)) { features2 += 0x00040000; } // Indicates 2FA backup codes are disabled
|
||||
if ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.single2factorwarning === false)) { features2 += 0x00080000; } // Indicates no warning if a single 2FA is in use
|
||||
if (domain.nightmode === 1) { features2 += 0x00100000; } // Always night mode
|
||||
if (domain.nightmode === 2) { features2 += 0x00200000; } // Always day mode
|
||||
return { features: features, features2: features2 };
|
||||
}
|
||||
|
||||
@ -2903,7 +2909,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
delete req.session.messageid;
|
||||
delete req.session.passhint;
|
||||
}
|
||||
var emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
const allowAccountReset = ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.allowaccountreset !== false));
|
||||
const emailcheck = (allowAccountReset && (domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
|
||||
// Check if we are allowed to create new users using the login screen
|
||||
var newAccountsAllowed = true;
|
||||
@ -4946,7 +4953,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
if (domain.agentcustomization.filename != null) { meshsettings += 'fileName=' + domain.agentcustomization.filename + '\r\n'; }
|
||||
if (domain.agentcustomization.image != null) { meshsettings += 'image=' + domain.agentcustomization.image + '\r\n'; }
|
||||
}
|
||||
if (parent.agentTranslations != null) { meshsettings += 'translation=' + parent.agentTranslations + '\r\n'; } // Translation strings, not for MeshCentral Assistant
|
||||
if (domain.agentTranslations != null) { meshsettings += 'translation=' + domain.agentTranslations + '\r\n'; } // Translation strings, not for MeshCentral Assistant
|
||||
}
|
||||
setContentDispositionHeader(res, 'application/octet-stream', meshfilename, null, argentInfo.rname);
|
||||
if (argentInfo.mtime != null) { res.setHeader('Last-Modified', argentInfo.mtime.toUTCString()); }
|
||||
@ -5318,7 +5325,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
if (domain.agentcustomization.filename != null) { meshsettings += 'fileName=' + domain.agentcustomization.filename + '\r\n'; }
|
||||
if (domain.agentcustomization.image != null) { meshsettings += 'image=' + domain.agentcustomization.image + '\r\n'; }
|
||||
}
|
||||
if (parent.agentTranslations != null) { meshsettings += 'translation=' + parent.agentTranslations + '\r\n'; }
|
||||
if (domain.agentTranslations != null) { meshsettings += 'translation=' + domain.agentTranslations + '\r\n'; }
|
||||
|
||||
// Setup the response output
|
||||
var archive = require('archiver')('zip', { level: 5 }); // Sets the compression method.
|
||||
@ -5419,7 +5426,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
if (domain.agentcustomization.filename != null) { meshsettings += 'fileName=' + domain.agentcustomization.filename + '\r\n'; }
|
||||
if (domain.agentcustomization.image != null) { meshsettings += 'image=' + domain.agentcustomization.image + '\r\n'; }
|
||||
}
|
||||
if (parent.agentTranslations != null) { meshsettings += 'translation=' + parent.agentTranslations + '\r\n'; }
|
||||
if (domain.agentTranslations != null) { meshsettings += 'translation=' + domain.agentTranslations + '\r\n'; }
|
||||
return meshsettings;
|
||||
}
|
||||
|
||||
@ -6456,7 +6463,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
var user = obj.users[userid];
|
||||
if ((err == null) && (user)) {
|
||||
// Check if a 2nd factor is needed
|
||||
var emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
const emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
|
||||
// See if we support two-factor trusted cookies
|
||||
var twoFactorCookieDays = 30;
|
||||
@ -6586,7 +6593,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
// Check if inner authentication is requested
|
||||
if (req.headers['x-meshauth'] === '*') { func(ws, req, domain, null); return; }
|
||||
|
||||
var emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
const emailcheck = ((domain.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true) && (domain.auth != 'sspi') && (domain.auth != 'ldap'))
|
||||
|
||||
// A web socket session can be authenticated in many ways (Default user, session, user/pass and cookie). Check authentication here.
|
||||
if ((req.query.user != null) && (req.query.pass != null)) {
|
||||
@ -7440,6 +7447,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
var mobile = isMobileBrowser(req), minify = (domain.minify == true), p;
|
||||
if (req.query.mobile == '1') { mobile = true; } else if (req.query.mobile == '0') { mobile = false; }
|
||||
if (req.query.minify == '1') { minify = true; } else if (req.query.minify == '0') { minify = false; }
|
||||
if ((domain != null) && (domain.mobilesite === false)) { mobile = false; }
|
||||
if (mobile) {
|
||||
if ((domain != null) && (domain.webviewspath != null)) { // If the domain has a web views path, use that first
|
||||
if (minify) {
|
||||
|
Loading…
Reference in New Issue
Block a user