ldap: mailbox routes now require the cn to be fully qualified
This commit is contained in:
+26
-22
@@ -258,14 +258,11 @@ function mailboxSearch(req, res, next) {
|
||||
|
||||
if (!req.dn.rdns[0].attrs.cn) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
var name = req.dn.rdns[0].attrs.cn.value.toLowerCase();
|
||||
// allow login via email
|
||||
var parts = name.split('@');
|
||||
if (parts[1] === config.fqdn()) {
|
||||
name = parts[0];
|
||||
}
|
||||
var email = req.dn.rdns[0].attrs.cn.value.toLowerCase();
|
||||
var parts = email.split('@');
|
||||
if (parts.length !== 2) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
mailboxdb.getMailbox(name, config.fqdn(), function (error, mailbox) {
|
||||
mailboxdb.getMailbox(parts[0], parts[1], function (error, mailbox) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.toString()));
|
||||
|
||||
@@ -276,7 +273,7 @@ function mailboxSearch(req, res, next) {
|
||||
objectcategory: 'mailbox',
|
||||
cn: mailbox.name,
|
||||
uid: mailbox.name,
|
||||
mail: mailbox.name + '@' + config.fqdn(),
|
||||
mail: mailbox.name + '@' + mailbox.domain,
|
||||
ownerType: mailbox.ownerType
|
||||
}
|
||||
};
|
||||
@@ -298,7 +295,11 @@ function mailAliasSearch(req, res, next) {
|
||||
|
||||
if (!req.dn.rdns[0].attrs.cn) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
mailboxdb.getAlias(req.dn.rdns[0].attrs.cn.value.toLowerCase(), config.fqdn(), function (error, alias) {
|
||||
var email = req.dn.rdns[0].attrs.cn.value.toLowerCase();
|
||||
var parts = email.split('@');
|
||||
if (parts.length !== 2) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
mailboxdb.getAlias(parts[0], parts[1], function (error, alias) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.toString()));
|
||||
|
||||
@@ -331,7 +332,11 @@ function mailingListSearch(req, res, next) {
|
||||
|
||||
if (!req.dn.rdns[0].attrs.cn) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
mailboxdb.getGroup(req.dn.rdns[0].attrs.cn.value.toLowerCase(), config.fqdn(), function (error, group) {
|
||||
var email = req.dn.rdns[0].attrs.cn.value.toLowerCase();
|
||||
var parts = email.split('@');
|
||||
if (parts.length !== 2) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
mailboxdb.getGroup(parts[0], parts[1], function (error, group) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.toString()));
|
||||
|
||||
@@ -342,7 +347,7 @@ function mailingListSearch(req, res, next) {
|
||||
objectclass: ['mailGroup'],
|
||||
objectcategory: 'mailGroup',
|
||||
cn: group.name,
|
||||
mail: group.name + '@' + config.fqdn(),
|
||||
mail: group.name + '@' + group.domain,
|
||||
mgrpRFC822MailMember: group.members
|
||||
}
|
||||
};
|
||||
@@ -411,15 +416,11 @@ function authorizeUserForApp(req, res, next) {
|
||||
function authenticateMailbox(req, res, next) {
|
||||
if (!req.dn.rdns[0].attrs.cn) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
var name = req.dn.rdns[0].attrs.cn.value.toLowerCase();
|
||||
var email = req.dn.rdns[0].attrs.cn.value.toLowerCase();
|
||||
var parts = email.split('@');
|
||||
if (parts.length !== 2) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
// allow login via email
|
||||
var parts = name.split('@');
|
||||
if (parts[1] === config.fqdn()) {
|
||||
name = parts[0];
|
||||
}
|
||||
|
||||
mailboxdb.getMailbox(name, config.fqdn(), function (error, mailbox) {
|
||||
mailboxdb.getMailbox(parts[0], parts[1], function (error, mailbox) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.message));
|
||||
|
||||
@@ -438,9 +439,12 @@ function authenticateMailbox(req, res, next) {
|
||||
return res.end();
|
||||
});
|
||||
} else if (mailbox.ownerType === mailboxdb.TYPE_USER) {
|
||||
authenticateUser(req, res, function (error) {
|
||||
if (error) return next(error);
|
||||
eventlog.add(eventlog.ACTION_USER_LOGIN, { authType: 'ldap', mailboxId: name }, { userId: req.user.username });
|
||||
user.verifyWithEmail(email, req.credentials || '', function (error, user) {
|
||||
if (error && error.reason === UserError.NOT_FOUND) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
if (error && error.reason === UserError.WRONG_PASSWORD) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.message));
|
||||
|
||||
eventlog.add(eventlog.ACTION_USER_LOGIN, { authType: 'ldap', mailboxId: email }, { userId: user.username });
|
||||
res.end();
|
||||
});
|
||||
} else {
|
||||
|
||||
+77
-41
@@ -729,8 +729,8 @@ describe('Ldap', function () {
|
||||
}
|
||||
|
||||
describe('search mailbox', function () {
|
||||
it('get specific mailbox', function (done) {
|
||||
ldapSearch('cn=' + USER_0.username + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error, entries) {
|
||||
it('get specific mailbox by email', function (done) {
|
||||
ldapSearch('cn=' + USER_0.username + '@example.com,ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error, entries) {
|
||||
if (error) return done(error);
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal(USER_0.username.toLowerCase());
|
||||
@@ -738,24 +738,22 @@ describe('Ldap', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('get specific mailbox by email', function (done) {
|
||||
ldapSearch('cn=' + USER_0.username + '@' + config.fqdn() + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error, entries) {
|
||||
if (error) return done(error);
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal(USER_0.username.toLowerCase());
|
||||
it('cannot get mailbox with just name', function (done) {
|
||||
ldapSearch('cn=' + USER_0.username + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error, entries) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot get alias as a mailbox', function (done) {
|
||||
ldapSearch('cn=' + USER_0_ALIAS + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
ldapSearch('cn=' + USER_0_ALIAS + '@example.com,ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('non-existent mailbox', function (done) {
|
||||
ldapSearch('cn=random,ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
ldapSearch('cn=random@example.com,ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
@@ -764,7 +762,7 @@ describe('Ldap', function () {
|
||||
|
||||
describe('search aliases', function () {
|
||||
it('get specific alias', function (done) {
|
||||
ldapSearch('cn=' + USER_0_ALIAS + ',ou=mailaliases,dc=cloudron', 'objectclass=nismailalias', function (error, entries) {
|
||||
ldapSearch('cn=' + USER_0_ALIAS + '@example.com,ou=mailaliases,dc=cloudron', 'objectclass=nismailalias', function (error, entries) {
|
||||
if (error) return done(error);
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal('asterix');
|
||||
@@ -774,14 +772,14 @@ describe('Ldap', function () {
|
||||
});
|
||||
|
||||
it('cannot get mailbox as alias', function (done) {
|
||||
ldapSearch('cn=' + USER_0.username + ',ou=mailaliases,dc=cloudron', 'objectclass=nismailalias', function (error) {
|
||||
ldapSearch('cn=' + USER_0.username + '@example.com,ou=mailaliases,dc=cloudron', 'objectclass=nismailalias', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('non-existent alias', function (done) {
|
||||
ldapSearch('cn=random,ou=mailaliases,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
ldapSearch('cn=random@example.com,ou=mailaliases,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
@@ -790,7 +788,7 @@ describe('Ldap', function () {
|
||||
|
||||
describe('search groups', function () {
|
||||
it('get specific alias', function (done) {
|
||||
ldapSearch('cn=' + USER_0_ALIAS + ',ou=mailaliases,dc=cloudron', 'objectclass=nismailalias', function (error, entries) {
|
||||
ldapSearch('cn=' + USER_0_ALIAS + '@example.com,ou=mailaliases,dc=cloudron', 'objectclass=nismailalias', function (error, entries) {
|
||||
if (error) return done(error);
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal('asterix');
|
||||
@@ -800,7 +798,7 @@ describe('Ldap', function () {
|
||||
});
|
||||
|
||||
it('non-existent alias', function (done) {
|
||||
ldapSearch('cn=random,ou=mailaliases,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
ldapSearch('cn=random@example.com,ou=mailaliases,dc=cloudron', 'objectclass=mailbox', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
@@ -809,7 +807,7 @@ describe('Ldap', function () {
|
||||
|
||||
describe('search mailing list', function () {
|
||||
it('get specific list', function (done) {
|
||||
ldapSearch('cn=developers,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup', function (error, entries) {
|
||||
ldapSearch('cn=developers@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup', function (error, entries) {
|
||||
if (error) return done(error);
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal('developers');
|
||||
@@ -819,7 +817,7 @@ describe('Ldap', function () {
|
||||
});
|
||||
|
||||
it('non-existent list', function (done) {
|
||||
ldapSearch('cn=random,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup', function (error) {
|
||||
ldapSearch('cn=random@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
done();
|
||||
});
|
||||
@@ -827,32 +825,32 @@ describe('Ldap', function () {
|
||||
});
|
||||
|
||||
describe('user sendmail bind', function () {
|
||||
it('does not allow with invalid password', function (done) {
|
||||
it('email disabled - cannot find domain email', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + ',ou=sendmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
client.bind('cn=' + USER_0.username + '@example.com,ou=sendmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
client.unbind(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('allows with valid password', function (done) {
|
||||
it('email disabled - cannot find reset email', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + ',ou=sendmail,dc=cloudron', USER_0.password, function (error) {
|
||||
client.unbind();
|
||||
done(error);
|
||||
client.bind('cn=' + USER_0.email + ',ou=sendmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
client.unbind(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('allows with valid email', function (done) {
|
||||
it('email enabled - allows with valid email', function (done) {
|
||||
// user settingsdb instead of settings, to not trigger further events
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
|
||||
expect(error).not.to.be.ok();
|
||||
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + '@' + config.fqdn() + ',ou=sendmail,dc=cloudron', USER_0.password, function (error) {
|
||||
client.bind('cn=' + USER_0.username + '@example.com,ou=sendmail,dc=cloudron', USER_0.password, function (error) {
|
||||
expect(error).not.to.be.ok();
|
||||
|
||||
client.unbind();
|
||||
@@ -861,13 +859,35 @@ describe('Ldap', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('email enabled - does not allow with invalid password', function (done) {
|
||||
// user settingsdb instead of settings, to not trigger further events
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
|
||||
expect(error).not.to.be.ok();
|
||||
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + '@example.com,ou=sendmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
|
||||
client.unbind();
|
||||
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('app sendmail bind', function () {
|
||||
// these tests should work even when email is disabled
|
||||
before(function (done) {
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
|
||||
});
|
||||
|
||||
it('does not allow with invalid app', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=hacker.app,ou=sendmail,dc=cloudron', 'nope', function (error) {
|
||||
client.bind('cn=hacker.app@example.com,ou=sendmail,dc=cloudron', 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
client.unbind(done);
|
||||
});
|
||||
@@ -876,7 +896,7 @@ describe('Ldap', function () {
|
||||
it('does not allow with invalid password', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + APP_0.location + '.app,ou=sendmail,dc=cloudron', 'nope', function (error) {
|
||||
client.bind('cn=' + APP_0.location + '.app@example.com,ou=sendmail,dc=cloudron', 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
client.unbind(done);
|
||||
});
|
||||
@@ -885,7 +905,7 @@ describe('Ldap', function () {
|
||||
it('allows with valid password', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + APP_0.location + '.app,ou=sendmail,dc=cloudron', 'sendmailpassword', function (error) {
|
||||
client.bind('cn=' + APP_0.location + '.app@example.com,ou=sendmail,dc=cloudron', 'sendmailpassword', function (error) {
|
||||
client.unbind();
|
||||
done(error);
|
||||
});
|
||||
@@ -893,33 +913,32 @@ describe('Ldap', function () {
|
||||
});
|
||||
|
||||
describe('user recvmail bind', function () {
|
||||
it('does not allow with invalid password', function (done) {
|
||||
it('email disabled - cannot find domain email', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + ',ou=recvmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
client.bind('cn=' + USER_0.username + '@example.com,ou=recvmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
client.unbind(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('allows with valid password', function (done) {
|
||||
it('email disabled - cannot find reset email', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + ',ou=recvmail,dc=cloudron', USER_0.password, function (error) {
|
||||
client.unbind();
|
||||
|
||||
done(error);
|
||||
client.bind('cn=' + USER_0.email + ',ou=recvmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
client.unbind(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('allows with valid email', function (done) {
|
||||
it('email enabled - allows with valid email', function (done) {
|
||||
// user settingsdb instead of settings, to not trigger further events
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
|
||||
expect(error).not.to.be.ok();
|
||||
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + '@' + config.fqdn() + ',ou=recvmail,dc=cloudron', USER_0.password, function (error) {
|
||||
client.bind('cn=' + USER_0.username + '@example.com,ou=recvmail,dc=cloudron', USER_0.password, function (error) {
|
||||
expect(error).not.to.be.ok();
|
||||
|
||||
client.unbind();
|
||||
@@ -928,13 +947,30 @@ describe('Ldap', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('email enabled - does not allow with invalid password', function (done) {
|
||||
// user settingsdb instead of settings, to not trigger further events
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
|
||||
expect(error).not.to.be.ok();
|
||||
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + USER_0.username + '@example.com,ou=recvmail,dc=cloudron', USER_0.password + 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
|
||||
client.unbind();
|
||||
|
||||
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('app recvmail bind', function () {
|
||||
it('does not allow with invalid app', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=hacker.app,ou=recvmail,dc=cloudron', 'nope', function (error) {
|
||||
client.bind('cn=hacker.app@example.com,ou=recvmail,dc=cloudron', 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
client.unbind(done);
|
||||
});
|
||||
@@ -943,7 +979,7 @@ describe('Ldap', function () {
|
||||
it('does not allow with invalid password', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + APP_0.location + '.app,ou=recvmail,dc=cloudron', 'nope', function (error) {
|
||||
client.bind('cn=' + APP_0.location + '.app@example.com,ou=recvmail,dc=cloudron', 'nope', function (error) {
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
client.unbind(done);
|
||||
});
|
||||
@@ -952,7 +988,7 @@ describe('Ldap', function () {
|
||||
it('allows with valid password', function (done) {
|
||||
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
|
||||
|
||||
client.bind('cn=' + APP_0.location + '.app,ou=recvmail,dc=cloudron', 'recvmailpassword', function (error) {
|
||||
client.bind('cn=' + APP_0.location + '.app@example.com,ou=recvmail,dc=cloudron', 'recvmailpassword', function (error) {
|
||||
client.unbind();
|
||||
|
||||
done(error);
|
||||
|
||||
Reference in New Issue
Block a user