ldap: send proper error messages
This commit is contained in:
@@ -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
@@ -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) });
|
||||
|
||||
Reference in New Issue
Block a user