Also auth against mailPasswords in ldapserver.js

This commit is contained in:
Johannes Zellner
2026-02-17 19:37:38 +01:00
parent bfbcbb686d
commit cb5ccd8166
3 changed files with 27 additions and 0 deletions
+1
View File
@@ -589,6 +589,7 @@ async function authenticateService(serviceId, dn, req, res, next) {
if (appPasswordError.reason !== BoxError.NOT_FOUND) return next(new ldap.OperationsError(appPasswordError.message));
if (!mailbox || !mailbox.active) return next(new ldap.NoSuchObjectError(dn.toString())); // user auth requires active mailbox
const [verifyError, result] = await safe(verifyMailboxPassword(mailbox, req.credentials || ''));
if (verifyError && verifyError.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(verifyError.message));
if (verifyError && verifyError.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(verifyError.message));
+7
View File
@@ -14,6 +14,12 @@ async function get(appId, userId) {
return result[0];
}
async function getByUserId(userId) {
assert.strictEqual(typeof userId, 'string');
return await database.query('SELECT ' + MAIL_PASSWORD_FIELDS + ' FROM mailPasswords WHERE userId = ?', [ userId ]);
}
async function add(appId, userId, password) {
assert.strictEqual(typeof appId, 'string');
assert.strictEqual(typeof userId, 'string');
@@ -50,6 +56,7 @@ async function del(appId, userId) {
export default {
get,
getByUserId,
add,
list,
del
+19
View File
@@ -11,6 +11,7 @@ import externalLdap from './externalldap.js';
import hat from './hat.js';
import mail from './mail.js';
import mailer from './mailer.js';
import mailPasswords from './mailpasswords.js';
import mysql from 'mysql2';
import notifications from './notifications.js';
import oidcClients from './oidcclients.js';
@@ -572,6 +573,17 @@ async function verifyAppPassword(userId, password, identifier) {
throw new BoxError(BoxError.INVALID_CREDENTIALS, 'Password is not valid');
}
async function verifyMailPassword(userId, password) {
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof password, 'string');
const result = await mailPasswords.getByUserId(userId);
if (result.find(r => r.password === password)) return;
throw new BoxError(BoxError.INVALID_CREDENTIALS, 'Password is not valid');
}
// identifier is only used to check if password is valid for a specific app
async function verify(user, password, identifier, options) {
assert.strictEqual(typeof user, 'object');
@@ -602,6 +614,13 @@ async function verify(user, password, identifier, options) {
return user;
}
const [mailPasswordError] = await safe(verifyMailPassword(user.id, password));
if (!mailPasswordError) { // matched app password
debug(`verify: ${user.username || user.id} matched mail password`);
user.mailPassword = true;
return user;
}
let localTotpCheck; // does 2fa need to be verified with local database 2fa creds
if (user.source === 'ldap') {
await externalLdap.verifyPassword(user.username, password, options);