mail: owner can be a group
This commit is contained in:
+35
-8
@@ -14,6 +14,7 @@ var addons = require('./addons.js'),
|
||||
constants = require('./constants.js'),
|
||||
debug = require('debug')('box:ldap'),
|
||||
eventlog = require('./eventlog.js'),
|
||||
groups = require('./groups.js'),
|
||||
ldap = require('ldapjs'),
|
||||
mail = require('./mail.js'),
|
||||
mailboxdb = require('./mailboxdb.js'),
|
||||
@@ -133,8 +134,8 @@ function userSearch(req, res, next) {
|
||||
|
||||
var dn = ldap.parseDN('cn=' + user.id + ',ou=users,dc=cloudron');
|
||||
|
||||
var groups = [ GROUP_USERS_DN ];
|
||||
if (users.compareRoles(user.role, users.ROLE_ADMIN) >= 0) groups.push(GROUP_ADMINS_DN);
|
||||
var memberof = [ GROUP_USERS_DN ];
|
||||
if (users.compareRoles(user.role, users.ROLE_ADMIN) >= 0) memberof.push(GROUP_ADMINS_DN);
|
||||
|
||||
var displayName = user.displayName || user.username || ''; // displayName can be empty and username can be null
|
||||
var nameParts = displayName.split(' ');
|
||||
@@ -155,7 +156,7 @@ function userSearch(req, res, next) {
|
||||
givenName: firstName,
|
||||
username: user.username,
|
||||
samaccountname: user.username, // to support ActiveDirectory clients
|
||||
memberof: groups
|
||||
memberof: memberof
|
||||
}
|
||||
};
|
||||
|
||||
@@ -328,7 +329,9 @@ function mailboxSearch(req, res, next) {
|
||||
async.eachSeries(mailboxes, function (mailbox, callback) {
|
||||
var dn = ldap.parseDN(`cn=${mailbox.name}@${mailbox.domain},ou=mailboxes,dc=cloudron`);
|
||||
|
||||
users.get(mailbox.ownerId, function (error, userObject) {
|
||||
let getFunc = mailbox.ownerType === mail.OWNERTYPE_USER ? users.get : groups.get;
|
||||
|
||||
getFunc(mailbox.ownerId, function (error, ownerObject) {
|
||||
if (error) return callback(); // skip mailboxes with unknown owner
|
||||
|
||||
var obj = {
|
||||
@@ -336,7 +339,7 @@ function mailboxSearch(req, res, next) {
|
||||
attributes: {
|
||||
objectclass: ['mailbox'],
|
||||
objectcategory: 'mailbox',
|
||||
displayname: userObject.displayName,
|
||||
displayname: mailbox.ownerType === mail.OWNERTYPE_USER ? ownerObject.displayName : ownerObject.name,
|
||||
cn: `${mailbox.name}@${mailbox.domain}`,
|
||||
uid: `${mailbox.name}@${mailbox.domain}`,
|
||||
mail: `${mailbox.name}@${mailbox.domain}`
|
||||
@@ -495,6 +498,30 @@ function authorizeUserForApp(req, res, next) {
|
||||
});
|
||||
}
|
||||
|
||||
function verifyMailboxPassword(mailbox, password, callback) {
|
||||
assert.strictEqual(typeof mailbox, 'object');
|
||||
assert.strictEqual(typeof password, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
if (mailbox.ownerType === mail.OWNERTYPE_USER) return users.verify(mailbox.ownerId, password, users.AP_MAIL /* identifier */, callback);
|
||||
|
||||
groups.getMembers(mailbox.ownerId, function (error, userIds) {
|
||||
if (error) return callback(error);
|
||||
|
||||
let verifiedUser = null;
|
||||
async.someSeries(userIds, function iterator(userId, iteratorDone) {
|
||||
users.verify(userId, password, users.AP_MAIL /* identifier */, function (error, result) {
|
||||
if (error) return iteratorDone(null, false);
|
||||
verifiedUser = result;
|
||||
iteratorDone(null, true);
|
||||
});
|
||||
}, function (error, result) {
|
||||
if (!result) return callback(new BoxError(BoxError.INVALID_CREDENTIALS));
|
||||
callback(null, verifiedUser);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function authenticateUserMailbox(req, res, next) {
|
||||
debug('user mailbox auth: %s (from %s)', req.dn.toString(), req.connection.ldap.id);
|
||||
|
||||
@@ -514,7 +541,7 @@ function authenticateUserMailbox(req, res, next) {
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.message));
|
||||
|
||||
users.verify(mailbox.ownerId, req.credentials || '', users.AP_MAIL, function (error, result) {
|
||||
verifyMailboxPassword(mailbox, req.credentials || '', function (error, result) {
|
||||
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) return next(new ldap.OperationsError(error.message));
|
||||
@@ -638,7 +665,7 @@ function authenticateMailAddon(req, res, next) {
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.message));
|
||||
|
||||
users.verify(mailbox.ownerId, req.credentials || '', users.AP_MAIL, function (error, result) {
|
||||
verifyMailboxPassword(mailbox, req.credentials || '', function (error, result) {
|
||||
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) return next(new ldap.OperationsError(error.message));
|
||||
@@ -674,7 +701,7 @@ function start(callback) {
|
||||
gServer.bind('ou=users,dc=cloudron', authenticateApp, authenticateUser, authorizeUserForApp);
|
||||
|
||||
// http://www.ietf.org/proceedings/43/I-D/draft-srivastava-ldap-mail-00.txt
|
||||
gServer.search('ou=mailboxes,dc=cloudron', mailboxSearch); // haraka (address translation), dovecot (LMTP)
|
||||
gServer.search('ou=mailboxes,dc=cloudron', mailboxSearch); // haraka (address translation), dovecot (LMTP), sogo (mailbox search)
|
||||
gServer.bind('ou=mailboxes,dc=cloudron', authenticateUserMailbox); // apps like sogo can use domain=${domain} to authenticate a mailbox
|
||||
gServer.search('ou=mailaliases,dc=cloudron', mailAliasSearch); // haraka
|
||||
gServer.search('ou=mailinglists,dc=cloudron', mailingListSearch); // haraka
|
||||
|
||||
Reference in New Issue
Block a user