From 87411b099ee600e3df8f134a697b3d7265897154 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Mon, 25 Nov 2019 14:30:23 -0800 Subject: [PATCH] Added support for multiple login 3FA keys. --- meshcentral.js | 1 + views/default.handlebars | 23 ++++++++++++----------- webserver.js | 34 +++++++++++++++++----------------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/meshcentral.js b/meshcentral.js index df75489c..2e8ba814 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -722,6 +722,7 @@ function CreateMeshCentralServer(config, args) { if (obj.config.domains[i].limits == null) { obj.config.domains[i].limits = {}; } if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; } obj.config.domains[i].id = i; + if (typeof obj.config.domains[i].loginkey == 'string') { obj.config.domains[i].loginkey = [obj.config.domains[i].loginkey]; } if (typeof obj.config.domains[i].userallowedip == 'string') { if (obj.config.domains[i].userallowedip == '') { obj.config.domains[i].userallowedip = null; } else { obj.config.domains[i].userallowedip = obj.config.domains[i].userallowedip.split(','); } } if (typeof obj.config.domains[i].userblockedip == 'string') { if (obj.config.domains[i].userblockedip == '') { obj.config.domains[i].userblockedip = null; } else { obj.config.domains[i].userblockedip = obj.config.domains[i].userallowedip.split(','); } } if (typeof obj.config.domains[i].agentallowedip == 'string') { if (obj.config.domains[i].agentallowedip == '') { obj.config.domains[i].agentallowedip = null; } else { obj.config.domains[i].agentallowedip = obj.config.domains[i].agentallowedip.split(','); } } diff --git a/views/default.handlebars b/views/default.handlebars index b63905d5..a169fb99 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -114,7 +114,6 @@ My Files My Users My Server -   @@ -163,15 +162,6 @@ -
@@ -9422,6 +9412,7 @@ // My Server if ((x == 6) || (x == 115)) QC('MainMenuMyServer').add(mainMenuActiveClass); if ((x == 6) || (x == 115) || (x == 40) || (x == 41) || (x == 42)) QC('LeftMenuMyServer').add(leftMenuActiveClass); + QV('ServerPlugins', pluginHandler != null); // column_l max-height if (webPageStackMenu && (x >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); } @@ -9470,8 +9461,12 @@ } } - // Plugin + // + // Plugin Management + // + function updatePluginList(versInfo) { + if (pluginHandler == null) return; if (Array.isArray(versInfo)) { versInfo.forEach(function(v) { updatePluginList(v); }); } QV('pluginNoneNotice', installedPluginList.length == 0); if (installedPluginList.length) { @@ -9562,15 +9557,18 @@ } function refreshPluginLatest() { + if (pluginHandler == null) return; meshserver.send({ action: 'pluginLatestCheck' }); } function distributeCore() { + if (pluginHandler == null) return; meshserver.send({ action: 'distributeCore', nodes: nodes }); // All nodes the user has access to QV('pluginRestartNotice', false); } function pluginActionEx() { + if (pluginHandler == null) return; var act = Q('lastPluginAct').value, id = Q('lastPluginId').value, pVersUrl = Q('lastPluginVersion').value; switch(act) { @@ -9595,6 +9593,7 @@ } function pluginAction(elem, id) { + if (pluginHandler == null) return; if (elem.value == 'downgrade') { meshserver.send({ 'action': 'getpluginversions', 'id': id }); } else { @@ -9606,6 +9605,7 @@ } function goPlugin(pname, title) { + if (pluginHandler == null) return; /* let holder = Q('PluginSubMenu').querySelectorAll('tr')[0]; let loadedPluginsTDs = holder.querySelectorAll('td'); @@ -9661,6 +9661,7 @@ } function noGoPlugin(el) { + if (pluginHandler == null) return; /* QV('PluginSubMenuSpan', false); let loadedPluginsTDs = Q('PluginSubMenu').querySelectorAll('td'); diff --git a/webserver.js b/webserver.js index 0bf4c874..3f666630 100644 --- a/webserver.js +++ b/webserver.js @@ -497,7 +497,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleLogoutRequest(req, res) { const domain = checkUserIpAddress(req, res); if ((domain == null) || (domain.auth == 'sspi')) { parent.debug('web', 'handleLogoutRequest: failed checks.'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); // Destroy the user's session to log them out will be re-created next request @@ -635,7 +635,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleLoginRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); if (domain == null) { parent.debug('web', 'handleLoginRequest: invalid domain'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Check if this is a banned ip address if (obj.checkAllowLogin(req) == false) { @@ -789,7 +789,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleCreateAccountRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCreateAccountRequest: failed checks.'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Always lowercase the email address if (req.body.email) { req.body.email = req.body.email.toLowerCase(); } @@ -900,7 +900,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Called to process an account password reset function handleResetPasswordRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // 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')) { @@ -984,7 +984,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleResetAccountRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); if ((domain == null) || (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 != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Always lowercase the email address if (req.body.email) { req.body.email = req.body.email.toLowerCase(); } @@ -1077,7 +1077,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleCheckMailRequest(req, res) { const domain = checkUserIpAddress(req, res); if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCheckMailRequest: failed checks.'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (req.query.c != null) { var cookie = obj.parent.decodeCookie(req.query.c, obj.parent.mailserver.mailCookieEncryptionKey, 30); @@ -1179,7 +1179,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleAgentInviteRequest(req, res) { const domain = getDomain(req); if ((domain == null) || ((req.query.m == null) && (req.query.c == null))) { parent.debug('web', 'handleAgentInviteRequest: failed checks.'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (req.query.c != null) { // A cookie is specified in the query string, use that @@ -1207,7 +1207,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { parent.debug('web', 'handleDeleteAccountRequest()'); const domain = checkUserIpAddress(req, res); if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleDeleteAccountRequest: failed checks.'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key var user = null; if (req.body.authcookie) { @@ -1294,7 +1294,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handlePasswordChangeRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handlePasswordChangeRequest: failed checks (1).'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Check if the user is logged and we have all required parameters if (!req.session || !req.session.userid || !req.body.apassword0 || !req.body.apassword1 || (req.body.apassword1 != req.body.apassword2) || (req.session.domainid != domain.id)) { @@ -1335,7 +1335,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleRootRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); if (domain == null) { parent.debug('web', 'handleRootRequest: invalid domain.'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (!obj.args) { parent.debug('web', 'handleRootRequest: no obj.args.'); res.sendStatus(500); return; } if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) { @@ -1607,7 +1607,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleRootPostRequest(req, res) { const domain = checkUserIpAddress(req, res); if (domain == null) { parent.debug('web', 'handleTermsRequest: Bad domain'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key parent.debug('web', 'handleRootPostRequest, action: ' + req.body.action); switch (req.body.action) { @@ -1651,7 +1651,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleTermsRequest(req, res) { const domain = checkUserIpAddress(req, res); if (domain == null) { parent.debug('web', 'handleTermsRequest: Bad domain'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // See if term.txt was loaded from the database if ((parent.configurationFiles != null) && (parent.configurationFiles['terms.txt'] != null)) { @@ -1731,7 +1731,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleRootCertRequest(req, res) { const domain = getDomain(req); if (domain == null) { parent.debug('web', 'handleRootCertRequest: no domain'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { parent.debug('web', 'handleRootCertRequest: invalid ip'); return; } // Check server-wide IP filter only. parent.debug('web', 'handleRootCertRequest()'); try { @@ -1828,7 +1828,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleMeScriptRequest(req, res) { const domain = getDomain(req); if (domain == null) { parent.debug('web', 'handleMeScriptRequest: no domain'); res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { return; } // Check server-wide IP filter only. if (req.query.type == 1) { @@ -1857,7 +1857,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleDownloadUserFiles(req, res) { const domain = checkUserIpAddress(req, res); if (domain == null) { res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (obj.common.validateString(req.path, 1, 4096) == false) { res.sendStatus(404); return; } var domainname = 'domain', spliturl = decodeURIComponent(req.path).split('/'), filename = ''; @@ -2812,7 +2812,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleBackupRequest(req, res) { const domain = checkUserIpAddress(req, res); if (domain == null) { res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if ((!req.session) || (req.session == null) || (!req.session.userid) || (obj.parent.args.noserverbackup == 1)) { res.sendStatus(401); return; } var user = obj.users[req.session.userid]; if ((user == null) || ((user.siteadmin & 1) == 0)) { res.sendStatus(401); return; } // Check if we have server backup rights @@ -2845,7 +2845,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleRestoreRequest(req, res) { const domain = checkUserIpAddress(req, res); if (domain == null) { res.sendStatus(404); return; } - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (obj.parent.args.noserverbackup == 1) { res.sendStatus(401); return; } var authUserid = null; if ((req.session != null) && (typeof req.session.userid == 'string')) { authUserid = req.session.userid; }