Added option to turn off reset account on login screen.

Ylian Saint-Hilaire committed Feb 4, 2022 at 07:29 UTC 1f1a80739e768e31d6cd62fda9aa47c9263da97f
3 files changed +26 -10
meshcentral-config-schema.json
+2 -1
@@ -451,7 +451,8 @@
451 "loginTokens": { "type": "boolean", "default": true, "description": "Allows users to create alternative username/passwords for their account." },
452 "twoFactorTimeout": { "type": "integer", "default": 300, "description": "Maximum about of time the to wait for a 2FA token on the login page in seconds." },
453 "autofido2fa": { "type": "boolean", "default": false, "description": "If true and user account has FIDO key setup, 2FA login screen will automatically request FIDO 2FA." },
454 - "maxfidokeys": { "type": "integer", "default": null, "description": "Maximum number of FIDO/YubikeyOTP hardware 2FA keys that can be setup in a user account." }
454 + "maxfidokeys": { "type": "integer", "default": null, "description": "Maximum number of FIDO/YubikeyOTP hardware 2FA keys that can be setup in a user account." },
455 + "allowaccountreset": { "type": "boolean", "default": true, "description": "If set to false, the account reset option on the login screen will not be available to users." }
456 }
457 },
458 "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." },
package.json
+14 -2
@@ -36,6 +36,8 @@
36 "sample-config-advanced.json"
37 ],
38 "dependencies": {
39 + "@yetzt/nedb": "^1.8.0",
40 + "archiver": "^4.0.2",
41 "body-parser": "^1.19.0",
42 "cbor": "~5.2.0",
43 "compression": "^1.7.4",
@@ -43,13 +45,23 @@
45 "express": "^4.17.0",
46 "express-handlebars": "^3.1.0",
47 "express-ws": "^4.0.0",
48 + "image-size": "^1.0.1",
49 "ipcheck": "^0.1.0",
50 + "loadavg-windows": "^1.1.1",
51 "minimist": "^1.2.5",
52 "multiparty": "^4.2.1",
49 - "@yetzt/nedb": "^1.8.0",
53 "node-forge": "^1.0.0",
54 + "node-rdpjs-2": "^0.3.5",
55 + "node-windows": "^0.1.4",
56 + "nodemailer": "^6.7.2",
57 + "otplib": "^10.2.3",
58 + "pg": "^8.7.1",
59 + "pgtools": "^0.3.2",
60 + "ssh2": "^1.6.0",
61 + "web-push": "^3.4.5",
62 "ws": "^5.2.3",
52 - "yauzl": "^2.10.0"
63 + "yauzl": "^2.10.0",
64 + "yubikeyotp": "^0.2.0"
65 },
66 "engines": {
67 "node": ">=10.0.0"
webserver.js
+10 -7
@@ -1144,7 +1144,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
1144 }
1145
1146 // Check if email address needs to be confirmed
1147 - 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'))
1147 + 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'))
1148 if (emailcheck && (user.emailVerified !== true)) {
1149 parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page');
1150 req.session.messageid = 3; // "Email verification required" message
@@ -1165,7 +1165,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
1165 }
1166
1167 // Check if email address needs to be confirmed
1168 - 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'))
1168 + 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'))
1169 if (emailcheck && (user.emailVerified !== true)) {
1170 parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page');
1171 req.session.messageid = 3; // "Email verification required" message
@@ -1459,7 +1459,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
1459 if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
1460
1461 // Check everything is ok
1462 - 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')) {
1462 + const allowAccountReset = ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.allowaccountreset !== false));
1463 + 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')) {
1464 parent.debug('web', 'handleResetPasswordRequest: checks failed');
1465 delete req.session.u2f;
1466 delete req.session.loginmode;
@@ -1568,7 +1569,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
1569 function handleResetAccountRequest(req, res, direct) {
1570 const domain = checkUserIpAddress(req, res);
1571 if (domain == null) { return; }
1571 - 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; }
1572 + const allowAccountReset = ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.allowaccountreset !== false));
1573 + 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; }
1574 if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
1575 if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
1576
@@ -2903,7 +2905,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2905 delete req.session.messageid;
2906 delete req.session.passhint;
2907 }
2906 - 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'))
2908 + const allowAccountReset = ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.allowaccountreset !== false));
2909 + 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'))
2910
2911 // Check if we are allowed to create new users using the login screen
2912 var newAccountsAllowed = true;
@@ -6456,7 +6459,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
6459 var user = obj.users[userid];
6460 if ((err == null) && (user)) {
6461 // Check if a 2nd factor is needed
6459 - 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'))
6462 + 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'))
6463
6464 // See if we support two-factor trusted cookies
6465 var twoFactorCookieDays = 30;
@@ -6586,7 +6589,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
6589 // Check if inner authentication is requested
6590 if (req.headers['x-meshauth'] === '*') { func(ws, req, domain, null); return; }
6591
6589 - 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'))
6592 + 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'))
6593
6594 // A web socket session can be authenticated in many ways (Default user, session, user/pass and cookie). Check authentication here.
6595 if ((req.query.user != null) && (req.query.pass != null)) {