/* jslint node:true */ /* global it:false */ /* global describe:false */ /* global before:false */ /* global after:false */ 'use strict'; var appdb = require('../appdb.js'), apps = require('../apps.js'), async = require('async'), constants = require('../constants.js'), database = require('../database.js'), domains = require('../domains.js'), EventEmitter = require('events').EventEmitter, expect = require('expect.js'), groups = require('../groups.js'), ldapServer = require('../ldap.js'), maildb = require('../maildb.js'), mailboxdb = require('../mailboxdb.js'), ldap = require('ldapjs'), users = require('../users.js'); const DOMAIN_0 = { domain: 'example.com', zoneName: 'example.com', config: {}, provider: 'manual', fallbackCertificate: null, tlsConfig: { provider: 'fallback' } }; // owner var USER_0 = { username: 'userName0', password: 'Username0pass?1234', email: 'user0@' + DOMAIN_0.domain.toUpperCase(), displayName: 'User 0' }; var USER_0_ALIAS = 'Asterix'; // normal user var USER_1 = { username: 'Username1', password: 'Username1pass?12345', email: 'USER1@' + DOMAIN_0.domain, displayName: 'User 1' }; var USER_2 = { username: 'Username2', password: 'Username2pass?12345', email: 'USER2@' + DOMAIN_0.domain, displayName: 'User 2' }; var GROUP_ID, GROUP_NAME = 'developers'; var AUDIT_SOURCE = { ip: '1.2.3.4' }; var APP_0 = { id: 'appid-0', appStoreId: 'appStoreId-0', installationState: appdb.ISTATE_INSTALLED, errorMessage: null, runState: appdb.RSTATE_RUNNING, location: 'some-location-0', domain: DOMAIN_0.domain, manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' }, httpPort: null, containerId: 'someContainerId', portBindings: { port: 5678 }, health: null, accessRestriction: null, memoryLimit: 4294967296, mailboxName: 'some-location-0.app' }; function setup(done) { async.series([ database.initialize.bind(null), database._clear.bind(null), ldapServer.start.bind(null), domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE), maildb.add.bind(null, DOMAIN_0.domain, {}), function (callback) { users.createOwner(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE, function (error, result) { if (error) return callback(error); USER_0.id = result.id; callback(); }); }, function (callback) { appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0, function (error) { if (error) return callback(error); apps._MOCK_GET_BY_IP_APP_ID = APP_0.id; callback(); }); }, (done) => mailboxdb.addMailbox(USER_0.username.toLowerCase(), DOMAIN_0.domain, USER_0.id, done), (done) => mailboxdb.setAliasesForName(USER_0.username.toLowerCase(), DOMAIN_0.domain, [ USER_0_ALIAS.toLocaleLowerCase() ], done), appdb.update.bind(null, APP_0.id, { containerId: APP_0.containerId }), appdb.setAddonConfig.bind(null, APP_0.id, 'sendmail', [{ name: 'MAIL_SMTP_PASSWORD', value : 'sendmailpassword' }]), appdb.setAddonConfig.bind(null, APP_0.id, 'recvmail', [{ name: 'MAIL_IMAP_PASSWORD', value : 'recvmailpassword' }]), mailboxdb.addMailbox.bind(null, APP_0.location + '.app', APP_0.domain, APP_0.id), function (callback) { users.create(USER_1.username, USER_1.password, USER_1.email, USER_0.displayName, { invitor: USER_0 }, AUDIT_SOURCE, function (error, result) { if (error) return callback(error); USER_1.id = result.id; callback(null); }); }, function (callback) { users.create(USER_2.username, USER_2.password, USER_2.email, USER_0.displayName, { invitor: USER_0 }, AUDIT_SOURCE, function (error, result) { if (error) return callback(error); USER_2.id = result.id; callback(null); }); }, function (callback) { groups.create(GROUP_NAME, function (error, result) { if (error) return callback(error); GROUP_ID = result.id; callback(); }); }, function (callback) { async.series([ groups.addMember.bind(null, GROUP_ID, USER_0.id), groups.addMember.bind(null, GROUP_ID, USER_1.id) ], callback); } ], done); } function cleanup(done) { apps._MOCK_GET_BY_IP_APP_ID = ''; async.series([ ldapServer.stop, database._clear, database.uninitialize ], done); } describe('Ldap', function () { before(setup); after(cleanup); describe('bind', function () { it('fails for nonexisting user', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=doesnotexist,ou=users,dc=cloudron', 'password', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('fails with wrong password', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.id + ',ou=users,dc=cloudron', 'wrongpassword', function (error) { expect(error).to.be.a(ldap.InvalidCredentialsError); client.unbind(); done(); }); }); it('succeeds without accessRestriction', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.id + ',ou=users,dc=cloudron', USER_0.password, function (error) { expect(error).to.be(null); client.unbind(); done(); }); }); it('succeeds with username and without accessRestriction', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.username + ',ou=users,dc=cloudron', USER_0.password, function (error) { expect(error).to.be(null); client.unbind(); done(); }); }); it('succeeds with email and without accessRestriction', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.email + ',ou=users,dc=cloudron', USER_0.password, function (error) { expect(error).to.be(null); client.unbind(); done(); }); }); it('succeeds without accessRestriction when email is enabled', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.email.toLowerCase() + ',ou=users,dc=cloudron', USER_0.password, function (error) { expect(error).to.be(null); client.unbind(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); it('fails with username for mail attribute and without accessRestriction', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('mail=' + USER_0.username + ',ou=users,dc=cloudron', USER_0.password, function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('fails with accessRestriction denied', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); appdb.update(APP_0.id, { accessRestriction: { users: [ USER_0.id ], groups: [] }}, function (error) { expect(error).to.eql(null); client.bind('cn=' + USER_1.id + ',ou=users,dc=cloudron', USER_1.password, function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); }); it('succeeds with accessRestriction allowed', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); appdb.update(APP_0.id, { accessRestriction: { users: [ USER_1.id, USER_0.id ], groups: [] }}, function (error) { expect(error).to.eql(null); client.bind('cn=' + USER_0.id + ',ou=users,dc=cloudron', USER_0.password, function (error) { expect(error).to.be(null); client.unbind(); done(); }); }); }); }); describe('search users', function () { it ('fails for non existing tree', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: '(&(l=Seattle)(email=*@' + DOMAIN_0.domain + '))' }; client.search('o=example', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); result.on('error', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); result.on('end', function (result) { done(new Error('Should not succeed. Status ' + result.status)); }); }); }); it ('succeeds with basic filter', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectcategory=person' }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); entries.sort(function (a, b) { return a.username > b.username; }); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[0].mail).to.equal(USER_0.email.toLowerCase()); expect(entries[1].username).to.equal(USER_1.username.toLowerCase()); expect(entries[1].mail).to.equal(USER_1.email.toLowerCase()); client.unbind(); done(); }); }); }); it ('succeeds with pagination', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectcategory=person', paged: true }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); entries.sort(function (a, b) { return a.username > b.username; }); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[0].mail).to.equal(USER_0.email.toLowerCase()); expect(entries[1].username).to.equal(USER_1.username.toLowerCase()); expect(entries[1].mail).to.equal(USER_1.email.toLowerCase()); client.unbind(); done(); }); }); }); it ('succeeds with basic filter and email enabled', function (done) { // user settingsdb instead of settings, to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectcategory=person' }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); entries.sort(function (a, b) { return a.username > b.username; }); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[0].mailAlternateAddress).to.equal(USER_0.email.toLowerCase()); expect(entries[0].mail).to.equal(USER_0.email.toLowerCase()); expect(entries[1].username).to.equal(USER_1.username.toLowerCase()); expect(entries[1].mailAlternateAddress).to.equal(USER_1.email.toLowerCase()); expect(entries[1].mail).to.equal(USER_1.email.toLowerCase()); client.unbind(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); }); it ('succeeds with username wildcard filter', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: '&(objectcategory=person)(username=username*)' }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); entries.sort(function (a, b) { return a.username > b.username; }); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[1].username).to.equal(USER_1.username.toLowerCase()); client.unbind(); done(); }); }); }); it ('succeeds with username filter', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: '&(objectcategory=person)(username=' + USER_0.username + ')' }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(1); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[0].memberof.length).to.equal(2); client.unbind(); done(); }); }); }); it ('always lists admins', function (done) { appdb.update(APP_0.id, { accessRestriction: { users: [], groups: [] } }, function (error) { expect(error).to.be(null); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectcategory=person' }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(1); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[0].memberof.length).to.equal(2); client.unbind(); appdb.update(APP_0.id, { accessRestriction: null }, done); }); }); }); }); it ('does only list users who have access', function (done) { appdb.update(APP_0.id, { accessRestriction: { users: [], groups: [ GROUP_ID ] } }, function (error) { expect(error).to.be(null); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectcategory=person' }; client.search('ou=users,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); entries.sort(function (a, b) { return a.username > b.username; }); expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); expect(entries[1].username).to.equal(USER_1.username.toLowerCase()); client.unbind(); appdb.update(APP_0.id, { accessRestriction: null }, done); }); }); }); }); }); describe('search groups', function () { it ('succeeds with basic filter', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectclass=group' }; client.search('ou=groups,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); // ensure order for testability entries.sort(function (a, b) { return a.username < b.username; }); expect(entries[0].cn).to.equal('users'); expect(entries[0].memberuid.length).to.equal(3); expect(entries[0].memberuid[0]).to.equal(USER_0.id); expect(entries[0].memberuid[1]).to.equal(USER_1.id); expect(entries[0].memberuid[2]).to.equal(USER_2.id); expect(entries[1].cn).to.equal('admins'); // if only one entry, the array becomes a string :-/ expect(entries[1].memberuid).to.equal(USER_0.id); client.unbind(); done(); }); }); }); it ('succeeds with cn wildcard filter', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: '&(objectclass=group)(cn=*)' }; client.search('ou=groups,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); expect(entries[0].cn).to.equal('users'); expect(entries[0].memberuid.length).to.equal(3); expect(entries[0].memberuid[0]).to.equal(USER_0.id); expect(entries[0].memberuid[1]).to.equal(USER_1.id); expect(entries[0].memberuid[2]).to.equal(USER_2.id); expect(entries[1].cn).to.equal('admins'); // if only one entry, the array becomes a string :-/ expect(entries[1].memberuid).to.equal(USER_0.id); client.unbind(); done(); }); }); }); it('succeeds with memberuid filter', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: '&(objectclass=group)(memberuid=' + USER_1.id + ')' }; client.search('ou=groups,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(1); expect(entries[0].cn).to.equal('users'); expect(entries[0].memberuid.length).to.equal(3); client.unbind(); done(); }); }); }); it ('does only list users who have access', function (done) { appdb.update(APP_0.id, { accessRestriction: { users: [], groups: [ GROUP_ID ] } }, function (error) { expect(error).to.be(null); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: '&(objectclass=group)(cn=*)' }; client.search('ou=groups,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); expect(entries[0].cn).to.equal('users'); expect(entries[0].memberuid.length).to.equal(2); expect(entries[0].memberuid[0]).to.equal(USER_0.id); expect(entries[0].memberuid[1]).to.equal(USER_1.id); expect(entries[1].cn).to.equal('admins'); // if only one entry, the array becomes a string :-/ expect(entries[1].memberuid).to.equal(USER_0.id); client.unbind(); appdb.update(APP_0.id, { accessRestriction: null }, done); }); }); }); }); it ('succeeds with pagination', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: 'objectclass=group', paged: true }; client.search('ou=groups,dc=cloudron', opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); expect(entries.length).to.equal(2); // ensure order for testability entries.sort(function (a, b) { return a.username < b.username; }); expect(entries[0].cn).to.equal('users'); expect(entries[0].memberuid.length).to.equal(3); expect(entries[0].memberuid[0]).to.equal(USER_0.id); expect(entries[0].memberuid[1]).to.equal(USER_1.id); expect(entries[0].memberuid[2]).to.equal(USER_2.id); expect(entries[1].cn).to.equal('admins'); // if only one entry, the array becomes a string :-/ expect(entries[1].memberuid).to.equal(USER_0.id); client.unbind(); done(); }); }); }); }); // ldapsearch -LLL -E pr=10/noprompt -x -h localhost -p 3002 -b cn=userName0@example.com,ou=mailboxes,dc=cloudron objectclass=mailbox function ldapSearch(dn, filter, callback) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); var opts = { filter: filter, paged: true }; function done(error, entries) { client.unbind(); callback(error, entries); } client.search(dn, opts, function (error, result) { expect(error).to.be(null); expect(result).to.be.an(EventEmitter); var entries = []; result.on('searchEntry', function (entry) { entries.push(entry.object); }); result.on('error', done); result.on('end', function (result) { expect(result.status).to.equal(0); done(null, entries); }); }); } describe('search mailbox', function () { 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() + '@example.com'); done(); }); }); it('cannot get mailbox with just name', function (done) { ldapSearch('cn=' + USER_0.username + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); done(); }); }); it('cannot get alias as a mailbox', function (done) { 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@example.com,ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); done(); }); }); }); describe('search aliases', function () { it('get specific alias', function (done) { 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@example.com'); expect(entries[0].rfc822MailMember).to.equal(USER_0.username.toLowerCase() + '@example.com'); done(); }); }); it('cannot get mailbox as alias', function (done) { 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@example.com,ou=mailaliases,dc=cloudron', 'objectclass=mailbox', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); done(); }); }); }); describe('search groups', function () { it('get specific alias', function (done) { 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@example.com'); expect(entries[0].rfc822MailMember).to.equal(USER_0.username.toLowerCase() + '@example.com'); done(); }); }); it('non-existent alias', function (done) { ldapSearch('cn=random@example.com,ou=mailaliases,dc=cloudron', 'objectclass=mailbox', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); done(); }); }); }); describe('search mailing list', function () { before(function (done) { mailboxdb.addList('devs', DOMAIN_0.domain, [ USER_0.username.toLowerCase(), USER_1.username.toLowerCase() ], done); }); it('get specific list', function (done) { ldapSearch('cn=devs@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('devs@example.com'); expect(entries[0].mgrpRFC822MailMember).to.eql([ USER_0.username.toLowerCase() + '@example.com', USER_1.username.toLowerCase() + '@example.com' ]); done(); }); }); it('non-existent list', function (done) { ldapSearch('cn=random@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); done(); }); }); }); describe('user mailbox bind', function () { it('email disabled - cannot find domain email', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.username + '@example.com,domain=example.com,ou=mailboxes,dc=cloudron', USER_0.password + 'nope', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('email enabled - does not allow with invalid password', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.username + '@example.com,domain=example.com,ou=mailboxes,dc=cloudron', USER_0.password + 'nope', function (error) { expect(error).to.be.a(ldap.InvalidCredentialsError); client.unbind(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); it('email enabled - allows with valid password', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.username + '@example.com,domain=example.com,ou=mailboxes,dc=cloudron', USER_0.password, function (error) { expect(error).not.to.be.ok(); client.unbind(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); it('email enabled - cannot auth with alias', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0_ALIAS + '@example.com,domain=example.com,ou=mailboxes,dc=cloudron', USER_0.password, function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); }); describe('user sendmail bind', function () { it('email disabled - cannot find domain email', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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(); done(); }); }); it('email disabled - cannot find reset email', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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('email enabled - allows with valid email', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + USER_0.username.toLocaleLowerCase() + '@' + DOMAIN_0.domain + ',ou=sendmail,dc=cloudron', USER_0.password, function (error) { expect(error).not.to.be.ok(); client.unbind(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); it('email enabled - does not allow with invalid password', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); }); describe('app sendmail bind', function () { // these tests should work even when email is disabled before(function (done) { maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); it('does not allow with invalid app', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=hacker.app@example.com,ou=sendmail,dc=cloudron', 'nope', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('does not allow with invalid password', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + APP_0.location + '.app@example.com,ou=sendmail,dc=cloudron', 'nope', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('allows with valid password', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + APP_0.location + '.app@example.com,ou=sendmail,dc=cloudron', 'sendmailpassword', function (error) { client.unbind(); done(error); }); }); }); describe('user recvmail bind', function () { before(function (done) { maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); it('email disabled - cannot find domain email', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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('email disabled - cannot find reset email', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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('email enabled - allows with valid email', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); it('email enabled - does not allow with invalid password', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); 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(); maildb.update(DOMAIN_0.domain, { enabled: false }, done); }); }); }); }); describe('app recvmail bind', function () { before(function (done) { maildb.update(DOMAIN_0.domain, { enabled: true }, done); }); it('does not allow with invalid app', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=hacker.app@example.com,ou=recvmail,dc=cloudron', 'nope', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('does not allow with invalid password', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + APP_0.location + '.app@example.com,ou=recvmail,dc=cloudron', 'nope', function (error) { expect(error).to.be.a(ldap.NoSuchObjectError); client.unbind(); done(); }); }); it('allows with valid password', function (done) { var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + constants.LDAP_PORT }); client.bind('cn=' + APP_0.location + '.app@example.com,ou=recvmail,dc=cloudron', 'recvmailpassword', function (error) { client.unbind(); done(error); }); }); }); });