Added support for multiple login 3FA keys.

Ylian Saint-Hilaire committed Nov 25, 2019 at 14:30 UTC 87411b099ee600e3df8f134a697b3d7265897154
3 files changed +30 -28
meshcentral.js
+1
@@ -722,6 +722,7 @@ function CreateMeshCentralServer(config, args) {
722 if (obj.config.domains[i].limits == null) { obj.config.domains[i].limits = {}; }
723 if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; }
724 obj.config.domains[i].id = i;
725 + if (typeof obj.config.domains[i].loginkey == 'string') { obj.config.domains[i].loginkey = [obj.config.domains[i].loginkey]; }
726 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(','); } }
727 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(','); } }
728 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(','); } }
views/default.handlebars
+12 -11
@@ -114,7 +114,6 @@
114 <td tabindex=0 id=MainMenuMyFiles class="topbar_td style3x" onclick=go(5,event) onkeypress="if (event.key == 'Enter') go(5)">My Files</td>
115 <td tabindex=0 id=MainMenuMyUsers class="topbar_td style3x" onclick=go(4,event) onkeypress="if (event.key == 'Enter') go(4)">My Users</td>
116 <td tabindex=0 id=MainMenuMyServer class="topbar_td style3x" onclick=go(6,event) onkeypress="if (event.key == 'Enter') go(6)">My Server</td>
117 - <!-- <td tabindex=0 id=MainMenuMyPlugins class="topbar_td style3x" onclick=go(7,event) onkeypress="if (event.key == 'Enter') go(7)">My Plugins</td> -->
117 <td class="topbar_td_end style3">&nbsp;</td>
118 </tr>
119 </table>
@@ -163,15 +162,6 @@
162 </tr>
163 </table>
164 </div>
166 - <!--
167 - <div id=PluginSubMenuSpan>
168 - <table id=PluginSubMenu cellpadding=0 cellspacing=0 class=style1>
169 - <tr>
170 - <td onclick="goPlugin(-1)" onkeypress="if (event.key == 'Enter') goPlugin(-1)" class="topbar_td style3x">Home</td>
171 - </tr>
172 - </table>
173 - </div>
174 - -->
165 <div id=UserDummyMenuSpan>
166 <table id=UserDummyMenu cellpadding=0 cellspacing=0 class=style1>
167 <tr><td class=style3 style="">&nbsp;</td></tr>
@@ -9422,6 +9412,7 @@
9412 // My Server
9413 if ((x == 6) || (x == 115)) QC('MainMenuMyServer').add(mainMenuActiveClass);
9414 if ((x == 6) || (x == 115) || (x == 40) || (x == 41) || (x == 42)) QC('LeftMenuMyServer').add(leftMenuActiveClass);
9415 + QV('ServerPlugins', pluginHandler != null);
9416
9417 // column_l max-height
9418 if (webPageStackMenu && (x >= 10)) { QC('column_l').add('room4submenu'); } else { QC('column_l').remove('room4submenu'); }
@@ -9470,8 +9461,12 @@
9461 }
9462 }
9463
9473 - // Plugin
9464 + //
9465 + // Plugin Management
9466 + //
9467 +
9468 function updatePluginList(versInfo) {
9469 + if (pluginHandler == null) return;
9470 if (Array.isArray(versInfo)) { versInfo.forEach(function(v) { updatePluginList(v); }); }
9471 QV('pluginNoneNotice', installedPluginList.length == 0);
9472 if (installedPluginList.length) {
@@ -9562,15 +9557,18 @@
9557 }
9558
9559 function refreshPluginLatest() {
9560 + if (pluginHandler == null) return;
9561 meshserver.send({ action: 'pluginLatestCheck' });
9562 }
9563
9564 function distributeCore() {
9565 + if (pluginHandler == null) return;
9566 meshserver.send({ action: 'distributeCore', nodes: nodes }); // All nodes the user has access to
9567 QV('pluginRestartNotice', false);
9568 }
9569
9570 function pluginActionEx() {
9571 + if (pluginHandler == null) return;
9572 var act = Q('lastPluginAct').value, id = Q('lastPluginId').value, pVersUrl = Q('lastPluginVersion').value;
9573
9574 switch(act) {
@@ -9595,6 +9593,7 @@
9593 }
9594
9595 function pluginAction(elem, id) {
9596 + if (pluginHandler == null) return;
9597 if (elem.value == 'downgrade') {
9598 meshserver.send({ 'action': 'getpluginversions', 'id': id });
9599 } else {
@@ -9606,6 +9605,7 @@
9605 }
9606
9607 function goPlugin(pname, title) {
9608 + if (pluginHandler == null) return;
9609 /*
9610 let holder = Q('PluginSubMenu').querySelectorAll('tr')[0];
9611 let loadedPluginsTDs = holder.querySelectorAll('td');
@@ -9661,6 +9661,7 @@
9661 }
9662
9663 function noGoPlugin(el) {
9664 + if (pluginHandler == null) return;
9665 /*
9666 QV('PluginSubMenuSpan', false);
9667 let loadedPluginsTDs = Q('PluginSubMenu').querySelectorAll('td');
webserver.js
+17 -17
@@ -497,7 +497,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
497 function handleLogoutRequest(req, res) {
498 const domain = checkUserIpAddress(req, res);
499 if ((domain == null) || (domain.auth == 'sspi')) { parent.debug('web', 'handleLogoutRequest: failed checks.'); res.sendStatus(404); return; }
500 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
500 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
501
502 res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
503 // 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) {
635 function handleLoginRequest(req, res, direct) {
636 const domain = checkUserIpAddress(req, res);
637 if (domain == null) { parent.debug('web', 'handleLoginRequest: invalid domain'); res.sendStatus(404); return; }
638 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
638 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
639
640 // Check if this is a banned ip address
641 if (obj.checkAllowLogin(req) == false) {
@@ -789,7 +789,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
789 function handleCreateAccountRequest(req, res, direct) {
790 const domain = checkUserIpAddress(req, res);
791 if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCreateAccountRequest: failed checks.'); res.sendStatus(404); return; }
792 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
792 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
793
794 // Always lowercase the email address
795 if (req.body.email) { req.body.email = req.body.email.toLowerCase(); }
@@ -900,7 +900,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
900 // Called to process an account password reset
901 function handleResetPasswordRequest(req, res, direct) {
902 const domain = checkUserIpAddress(req, res);
903 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
903 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
904
905 // Check everything is ok
906 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) {
984 function handleResetAccountRequest(req, res, direct) {
985 const domain = checkUserIpAddress(req, res);
986 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; }
987 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
987 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
988
989 // Always lowercase the email address
990 if (req.body.email) { req.body.email = req.body.email.toLowerCase(); }
@@ -1077,7 +1077,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1077 function handleCheckMailRequest(req, res) {
1078 const domain = checkUserIpAddress(req, res);
1079 if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCheckMailRequest: failed checks.'); res.sendStatus(404); return; }
1080 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1080 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1081
1082 if (req.query.c != null) {
1083 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) {
1179 function handleAgentInviteRequest(req, res) {
1180 const domain = getDomain(req);
1181 if ((domain == null) || ((req.query.m == null) && (req.query.c == null))) { parent.debug('web', 'handleAgentInviteRequest: failed checks.'); res.sendStatus(404); return; }
1182 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1182 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1183
1184 if (req.query.c != null) {
1185 // A cookie is specified in the query string, use that
@@ -1207,7 +1207,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1207 parent.debug('web', 'handleDeleteAccountRequest()');
1208 const domain = checkUserIpAddress(req, res);
1209 if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleDeleteAccountRequest: failed checks.'); res.sendStatus(404); return; }
1210 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1210 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1211
1212 var user = null;
1213 if (req.body.authcookie) {
@@ -1294,7 +1294,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1294 function handlePasswordChangeRequest(req, res, direct) {
1295 const domain = checkUserIpAddress(req, res);
1296 if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handlePasswordChangeRequest: failed checks (1).'); res.sendStatus(404); return; }
1297 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1297 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1298
1299 // Check if the user is logged and we have all required parameters
1300 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) {
1335 function handleRootRequest(req, res, direct) {
1336 const domain = checkUserIpAddress(req, res);
1337 if (domain == null) { parent.debug('web', 'handleRootRequest: invalid domain.'); res.sendStatus(404); return; }
1338 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1338 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1339 if (!obj.args) { parent.debug('web', 'handleRootRequest: no obj.args.'); res.sendStatus(500); return; }
1340
1341 if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) {
@@ -1607,7 +1607,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1607 function handleRootPostRequest(req, res) {
1608 const domain = checkUserIpAddress(req, res);
1609 if (domain == null) { parent.debug('web', 'handleTermsRequest: Bad domain'); res.sendStatus(404); return; }
1610 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1610 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1611 parent.debug('web', 'handleRootPostRequest, action: ' + req.body.action);
1612
1613 switch (req.body.action) {
@@ -1651,7 +1651,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1651 function handleTermsRequest(req, res) {
1652 const domain = checkUserIpAddress(req, res);
1653 if (domain == null) { parent.debug('web', 'handleTermsRequest: Bad domain'); res.sendStatus(404); return; }
1654 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1654 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1655
1656 // See if term.txt was loaded from the database
1657 if ((parent.configurationFiles != null) && (parent.configurationFiles['terms.txt'] != null)) {
@@ -1731,7 +1731,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1731 function handleRootCertRequest(req, res) {
1732 const domain = getDomain(req);
1733 if (domain == null) { parent.debug('web', 'handleRootCertRequest: no domain'); res.sendStatus(404); return; }
1734 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1734 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1735 if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { parent.debug('web', 'handleRootCertRequest: invalid ip'); return; } // Check server-wide IP filter only.
1736 parent.debug('web', 'handleRootCertRequest()');
1737 try {
@@ -1828,7 +1828,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1828 function handleMeScriptRequest(req, res) {
1829 const domain = getDomain(req);
1830 if (domain == null) { parent.debug('web', 'handleMeScriptRequest: no domain'); res.sendStatus(404); return; }
1831 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1831 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1832
1833 if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { return; } // Check server-wide IP filter only.
1834 if (req.query.type == 1) {
@@ -1857,7 +1857,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1857 function handleDownloadUserFiles(req, res) {
1858 const domain = checkUserIpAddress(req, res);
1859 if (domain == null) { res.sendStatus(404); return; }
1860 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
1860 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1861
1862 if (obj.common.validateString(req.path, 1, 4096) == false) { res.sendStatus(404); return; }
1863 var domainname = 'domain', spliturl = decodeURIComponent(req.path).split('/'), filename = '';
@@ -2812,7 +2812,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2812 function handleBackupRequest(req, res) {
2813 const domain = checkUserIpAddress(req, res);
2814 if (domain == null) { res.sendStatus(404); return; }
2815 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
2815 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
2816 if ((!req.session) || (req.session == null) || (!req.session.userid) || (obj.parent.args.noserverbackup == 1)) { res.sendStatus(401); return; }
2817 var user = obj.users[req.session.userid];
2818 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) {
2845 function handleRestoreRequest(req, res) {
2846 const domain = checkUserIpAddress(req, res);
2847 if (domain == null) { res.sendStatus(404); return; }
2848 - if ((domain.loginkey != null) && (domain.loginkey != req.query.key)) { res.sendStatus(404); return; } // Check 3FA URL key
2848 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
2849 if (obj.parent.args.noserverbackup == 1) { res.sendStatus(401); return; }
2850 var authUserid = null;
2851 if ((req.session != null) && (typeof req.session.userid == 'string')) { authUserid = req.session.userid; }