ldap: send proper error messages

This commit is contained in:
Girish Ramakrishnan
2024-01-03 14:51:00 +01:00
parent 10172e0211
commit 96be06188b
2 changed files with 35 additions and 35 deletions
+8 -8
View File
@@ -199,10 +199,10 @@ async function userSearch(req, res, next) {
debug('user search: dn %s, scope %s, filter %s (from %s)', req.dn.toString(), req.scope, req.filter.toString(), req.connection.ldap.id);
const [error, allUsers] = await safe(users.list());
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
const [groupsError, allGroups] = await safe(groups.listWithMembers());
if (groupsError) return next(new ldap.OperationsError(error.toString()));
if (groupsError) return next(new ldap.OperationsError(groupsError.message));
let results = [];
@@ -244,7 +244,7 @@ async function userSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if ((req.dn.equals(dn) || req.dn.parentOf(dn)) && lowerCaseFilter.matches(obj.attributes)) {
results.push(obj);
@@ -258,12 +258,12 @@ async function groupSearch(req, res, next) {
debug('group search: dn %s, scope %s, filter %s (from %s)', req.dn.toString(), req.scope, req.filter.toString(), req.connection.ldap.id);
const [error, allUsers] = await safe(users.list());
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
const results = [];
let [errorGroups, allGroups] = await safe(groups.listWithMembers());
if (errorGroups) return next(new ldap.OperationsError(errorGroups.toString()));
if (errorGroups) return next(new ldap.OperationsError(errorGroups.message));
for (const group of allGroups) {
const dn = ldap.parseDN(`cn=${group.name},ou=groups,dc=cloudron`);
@@ -283,7 +283,7 @@ async function groupSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if ((req.dn.equals(dn) || req.dn.parentOf(dn)) && lowerCaseFilter.matches(obj.attributes)) {
results.push(obj);
@@ -315,8 +315,8 @@ async function userAuth(req, res, next) {
}
const [error, user] = await safe(verifyFunc(commonName, req.credentials || '', '', { totpToken }));
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(error.message));
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(error.message));
if (error) return next(new ldap.OperationsError(error.message));
req.user = user;
+27 -27
View File
@@ -68,8 +68,8 @@ async function userAuthInternal(appId, req, res, next) {
}
const [error, user] = await safe(verifyFunc(commonName, req.credentials || '', appId || '', { relaxedTotpCheck: true, totpToken }));
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(error.message));
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(error.message));
if (error) return next(new ldap.OperationsError(error.message));
req.user = user;
@@ -149,10 +149,10 @@ async function userSearch(req, res, next) {
debug('user search: dn %s, scope %s, filter %s (from %s)', req.dn.toString(), req.scope, req.filter.toString(), req.connection.ldap.id);
const [error, result] = await safe(getUsersWithAccessToApp(req));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
const [groupsError, allGroups] = await safe(groups.listWithMembers());
if (groupsError) return next(new ldap.OperationsError(error.toString()));
if (groupsError) return next(new ldap.OperationsError(groupsError.message));
let results = [];
@@ -192,7 +192,7 @@ async function userSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if ((req.dn.equals(dn) || req.dn.parentOf(dn)) && lowerCaseFilter.matches(obj.attributes)) {
results.push(obj);
@@ -207,8 +207,8 @@ async function groupSearch(req, res, next) {
const results = [];
let [errorGroups, resultGroups] = await safe(groups.listWithMembers());
if (errorGroups) return next(new ldap.OperationsError(errorGroups.toString()));
let [groupsListError, resultGroups] = await safe(groups.listWithMembers());
if (groupsListError) return next(new ldap.OperationsError(groupsListError.message));
if (req.app.accessRestriction && req.app.accessRestriction.groups) {
resultGroups = resultGroups.filter(function (g) { return req.app.accessRestriction.groups.indexOf(g.id) !== -1; });
@@ -229,7 +229,7 @@ async function groupSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if ((req.dn.equals(dn) || req.dn.parentOf(dn)) && lowerCaseFilter.matches(obj.attributes)) {
results.push(obj);
@@ -243,7 +243,7 @@ async function groupUsersCompare(req, res, next) {
debug('group users compare: dn %s, attribute %s, value %s (from %s)', req.dn.toString(), req.attribute, req.value, req.connection.ldap.id);
const [error, result] = await safe(getUsersWithAccessToApp(req));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
// we only support memberuid here, if we add new group attributes later add them here
if (req.attribute === 'memberuid') {
@@ -258,7 +258,7 @@ async function groupAdminsCompare(req, res, next) {
debug('group admins compare: dn %s, attribute %s, value %s (from %s)', req.dn.toString(), req.attribute, req.value, req.connection.ldap.id);
const [error, result] = await safe(getUsersWithAccessToApp(req));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
// we only support memberuid here, if we add new group attributes later add them here
if (req.attribute === 'memberuid') {
@@ -287,9 +287,9 @@ async function mailboxSearch(req, res, next) {
if (parts.length !== 2) return next(new ldap.NoSuchObjectError(dn.toString()));
const [error, mailbox] = await safe(mail.getMailbox(parts[0], parts[1]));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
if (!mailbox) return next(new ldap.NoSuchObjectError(dn.toString()));
if (!mailbox.active) return next(new ldap.NoSuchObjectError(dn.toString()));
if (!mailbox.active) return next(new ldap.NoSuchObjectError('Mailbox is not active'));
const obj = {
dn: dn.toString(),
@@ -306,7 +306,7 @@ async function mailboxSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if (lowerCaseFilter.matches(obj.attributes)) {
finalSend([ obj ], req, res, next);
@@ -316,7 +316,7 @@ async function mailboxSearch(req, res, next) {
} else { // new sogo and dovecot listing (doveadm -A)
// TODO figure out how proper pagination here could work
let [error, mailboxes] = await safe(mail.listAllMailboxes(1, 100000));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
mailboxes = mailboxes.filter(m => m.active);
@@ -349,7 +349,7 @@ async function mailboxSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if ((req.dn.equals(dn) || req.dn.parentOf(dn)) && lowerCaseFilter.matches(obj.attributes)) {
results.push(obj);
@@ -370,10 +370,10 @@ async function mailAliasSearch(req, res, next) {
if (parts.length !== 2) return next(new ldap.NoSuchObjectError(req.dn.toString()));
const [error, alias] = await safe(mail.searchAlias(parts[0], parts[1]));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
if (!alias) return next(new ldap.NoSuchObjectError(req.dn.toString()));
if (!alias.active) return next(new ldap.NoSuchObjectError(req.dn.toString())); // there is no way to disable an alias. this is just here for completeness
if (!alias.active) return next(new ldap.NoSuchObjectError('Mailbox is not active')); // there is no way to disable an alias. this is just here for completeness
// https://wiki.debian.org/LDAP/MigrationTools/Examples
// https://docs.oracle.com/cd/E19455-01/806-5580/6jej518pp/index.html
@@ -390,7 +390,7 @@ async function mailAliasSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if (lowerCaseFilter.matches(obj.attributes)) {
finalSend([ obj ], req, res, next);
@@ -411,11 +411,11 @@ async function mailingListSearch(req, res, next) {
const [error, result] = await safe(mail.resolveList(parts[0], parts[1]));
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
const { resolvedMembers, list } = result;
if (!list.active) return next(new ldap.NoSuchObjectError(req.dn.toString()));
if (!list.active) return next(new ldap.NoSuchObjectError('List is not active'));
// http://ldapwiki.willeke.com/wiki/Original%20Mailgroup%20Schema%20From%20Netscape
// members are fully qualified (https://docs.oracle.com/cd/E19444-01/816-6018-10/groups.htm#13356)
@@ -433,7 +433,7 @@ async function mailingListSearch(req, res, next) {
// ensure all filter values are also lowercase
const lowerCaseFilter = safe(function () { return ldap.parseFilter(req.filter.toString().toLowerCase()); }, null);
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.toString()));
if (!lowerCaseFilter) return next(new ldap.OperationsError(safe.error.message));
if (lowerCaseFilter.matches(obj.attributes)) {
finalSend([ obj ], req, res, next);
@@ -501,7 +501,7 @@ async function authenticateSftp(req, res, next) {
if (error || !app) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
[error] = await safe(users.verifyWithUsername(parts[0], req.credentials, app.id, { relaxedTotpCheck: true }));
if (error) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
if (error) return next(new ldap.InvalidCredentialsError(error.message));
debug('sftp auth: success');
@@ -520,7 +520,7 @@ async function userSearchSftp(req, res, next) {
const appFqdn = parts[1];
const [error, app] = await safe(apps.getByFqdn(appFqdn));
if (error) return next(new ldap.OperationsError(error.toString()));
if (error) return next(new ldap.OperationsError(error.message));
// only allow apps which specify "ftp" support in the localstorage addon
if (!safe.query(app.manifest.addons, 'localstorage.ftp.uid')) return next(new ldap.UnavailableError('Not supported'));
@@ -529,7 +529,7 @@ async function userSearchSftp(req, res, next) {
const uidNumber = app.manifest.addons.localstorage.ftp.uid;
const [userGetError, user] = await safe(users.getByUsername(username));
if (userGetError) return next(new ldap.OperationsError(userGetError.toString()));
if (userGetError) return next(new ldap.OperationsError(userGetError.message));
if (!user) return next(new ldap.OperationsError('Invalid username'));
if (!apps.isOperator(app, user)) return next(new ldap.InsufficientAccessRightsError('Not authorized'));
@@ -595,13 +595,13 @@ async function authenticateService(serviceId, dn, req, res, next) {
const [appPasswordError] = await safe(verifyAppMailboxPassword(serviceId, email, req.credentials || ''));
if (!appPasswordError) return res.end(); // validated as app
if (appPasswordError.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(dn.toString()));
if (appPasswordError.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(appPasswordError.message));
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(dn.toString()));
if (verifyError && verifyError.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(dn.toString()));
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));
if (verifyError) return next(new ldap.OperationsError(verifyError.message));
eventlog.upsertLoginEvent(result.ghost ? eventlog.ACTION_USER_LOGIN_GHOST : eventlog.ACTION_USER_LOGIN, AuditSource.MAIL, { mailboxId: email, userId: result.id, user: users.removePrivateFields(result) });