rainbox.email/src/LDAPServerComponent.ts

77 lines
2.6 KiB
TypeScript
Raw Normal View History

2021-01-25 18:04:11 +01:00
import ApplicationComponent from "swaf/ApplicationComponent";
import ldap, {InvalidCredentialsError, Server} from "ldapjs";
2021-01-25 18:04:11 +01:00
import {logger} from "swaf/Logger";
import Throttler from "swaf/Throttler";
import User from "swaf/auth/models/User";
import UserPasswordComponent from "swaf/auth/password/UserPasswordComponent";
export default class LDAPServerComponent extends ApplicationComponent {
private server?: Server;
2020-11-02 19:27:18 +01:00
public async start(): Promise<void> {
this.server = ldap.createServer({
2020-11-02 19:27:18 +01:00
log: console,
});
2020-11-02 19:27:18 +01:00
this.server.bind('ou=users,dc=toot,dc=party', async (req: Record<string, string>, res: Record<string, () => void>, next: (err: unknown) => void) => {
const rdns = req.dn.toString().split(', ').map((rdn: string) => rdn.split('='));
2020-11-02 19:27:18 +01:00
let username: string = '';
let email;
for (const rdn of rdns) {
if (rdn[0] === 'cn') {
username = rdn[1];
} else if (rdn[0] === 'email') {
email = rdn[1];
}
}
2021-01-25 18:04:11 +01:00
logger.debug('Matrix authentication attempt:', username, email);
try {
Throttler.throttle('ldap_auth', 3, 30 * 1000, username);
} catch (e) {
2021-01-25 18:04:11 +01:00
logger.debug('Too many auth requests');
next(new InvalidCredentialsError());
return;
}
const user = await User.select().where('name', username).first();
if (user) {
const email = await user.mainEmail.get();
if (email) {
if (await user.as(UserPasswordComponent).verifyPassword(req.credentials)) {
2021-01-25 18:04:11 +01:00
logger.debug('Success');
res.end();
return;
}
}
}
2021-01-25 18:04:11 +01:00
logger.debug('Fail');
next(new InvalidCredentialsError());
});
2020-11-02 19:27:18 +01:00
this.server.unbind((req: unknown, res: unknown, next: () => void) => {
2021-01-25 18:04:11 +01:00
logger.debug('Unbind', req);
next();
});
this.server.listen(8389, '127.0.0.1', () => {
2021-01-25 18:04:11 +01:00
logger.info(`LDAP server listening on ${this.server?.url}`);
});
2020-07-30 11:59:25 +02:00
this.server.on('close', () => {
2021-01-25 18:04:11 +01:00
logger.info('LDAP server closed.');
2020-07-30 11:59:25 +02:00
});
}
public async stop(): Promise<void> {
2021-01-25 18:04:11 +01:00
await new Promise<void>(resolve => {
2020-07-30 11:59:25 +02:00
if (this.server) {
this.server.close(() => {
resolve();
});
} else {
resolve();
}
});
}
}