Added option to turn off reset account on login screen.

This commit is contained in:
Ylian Saint-Hilaire 2022-02-04 07:29:18 -08:00
parent 8a0cb6abfa
commit 1f1a80739e
3 changed files with 26 additions and 10 deletions

View File

@ -451,7 +451,8 @@
"loginTokens": { "type": "boolean", "default": true, "description": "Allows users to create alternative username/passwords for their account." }, "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." }, "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." }, "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." }, "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." },

View File

@ -36,6 +36,8 @@
"sample-config-advanced.json" "sample-config-advanced.json"
], ],
"dependencies": { "dependencies": {
"@yetzt/nedb": "^1.8.0",
"archiver": "^4.0.2",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"cbor": "~5.2.0", "cbor": "~5.2.0",
"compression": "^1.7.4", "compression": "^1.7.4",
@ -43,13 +45,23 @@
"express": "^4.17.0", "express": "^4.17.0",
"express-handlebars": "^3.1.0", "express-handlebars": "^3.1.0",
"express-ws": "^4.0.0", "express-ws": "^4.0.0",
"image-size": "^1.0.1",
"ipcheck": "^0.1.0", "ipcheck": "^0.1.0",
"loadavg-windows": "^1.1.1",
"minimist": "^1.2.5", "minimist": "^1.2.5",
"multiparty": "^4.2.1", "multiparty": "^4.2.1",
"@yetzt/nedb": "^1.8.0",
"node-forge": "^1.0.0", "node-forge": "^1.0.0",
"node-rdpjs-2": "^0.3.5",
"node-windows": "^0.1.4",
"nodemailer": "^6.7.2",
"otplib": "^10.2.3",
"pg": "^8.7.1",
"pgtools": "^0.3.2",
"ssh2": "^1.6.0",
"web-push": "^3.4.5",
"ws": "^5.2.3", "ws": "^5.2.3",
"yauzl": "^2.10.0" "yauzl": "^2.10.0",
"yubikeyotp": "^0.2.0"
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"

View File

@ -1144,7 +1144,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
} }
// Check if email address needs to be confirmed // 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)) { if (emailcheck && (user.emailVerified !== true)) {
parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page'); parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page');
req.session.messageid = 3; // "Email verification required" message 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 // 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)) { if (emailcheck && (user.emailVerified !== true)) {
parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page'); parent.debug('web', 'Redirecting using ' + user.name + ' to email check login page');
req.session.messageid = 3; // "Email verification required" message 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 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 // 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'); parent.debug('web', 'handleResetPasswordRequest: checks failed');
delete req.session.u2f; delete req.session.u2f;
delete req.session.loginmode; delete req.session.loginmode;
@ -1568,7 +1569,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
function handleResetAccountRequest(req, res, direct) { function handleResetAccountRequest(req, res, direct) {
const domain = checkUserIpAddress(req, res); const domain = checkUserIpAddress(req, res);
if (domain == null) { return; } 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 ((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 if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
@ -2903,7 +2905,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
delete req.session.messageid; delete req.session.messageid;
delete req.session.passhint; 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 // Check if we are allowed to create new users using the login screen
var newAccountsAllowed = true; var newAccountsAllowed = true;
@ -6456,7 +6459,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
var user = obj.users[userid]; var user = obj.users[userid];
if ((err == null) && (user)) { if ((err == null) && (user)) {
// Check if a 2nd factor is needed // 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 // See if we support two-factor trusted cookies
var twoFactorCookieDays = 30; var twoFactorCookieDays = 30;
@ -6586,7 +6589,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
// Check if inner authentication is requested // Check if inner authentication is requested
if (req.headers['x-meshauth'] === '*') { func(ws, req, domain, null); return; } 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. // 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)) { if ((req.query.user != null) && (req.query.pass != null)) {