'use strict'; module.exports = { state: 'Not Authenticated', schema: [ { name: 'username', type: 'string' }, { name: 'password', type: 'string' } ], handler(command, callback) { let username = Buffer.from((command.attributes[0].value || '').toString().trim(), 'binary').toString(); let password = Buffer.from((command.attributes[1].value || '').toString().trim(), 'binary').toString(); if (!this.secure && !this._server.options.disableSTARTTLS && !this._server.options.ignoreSTARTTLS) { // Only allow authentication using TLS return callback(null, { response: 'BAD', message: 'Run STARTTLS first' }); } // Check if authentication method is set if (typeof this._server.onAuth !== 'function') { this._server.logger.info( { tnx: 'auth', username, method: 'LOGIN', action: 'fail', cid: this.id }, '[%s] Authentication failed for %s using %s', this.id, username, 'LOGIN' ); return callback(null, { response: 'NO', message: 'Authentication not implemented' }); } // Do auth this._server.onAuth( { method: 'LOGIN', username, password }, this.session, (err, response) => { if (err) { if (err.response) { return callback(null, err); } this._server.logger.info( { err, tnx: 'auth', username, method: 'LOGIN', action: 'fail', cid: this.id }, '[%s] Authentication error for %s using %s\n%s', this.id, username, 'LOGIN', err.message ); return callback(err); } if (!response || !response.user) { this._server.logger.info( { tnx: 'auth', username, method: 'LOGIN', action: 'fail', cid: this.id }, '[%s] Authentication failed for %s using %s', this.id, username, 'LOGIN' ); return callback(null, { response: 'NO', code: 'AUTHENTICATIONFAILED', message: 'Invalid credentials' }); } this._server.logger.info( { tnx: 'auth', username, method: 'LOGIN', action: 'success', cid: this.id }, '[%s] %s authenticated using %s', this.id, username, 'LOGIN' ); this.setUser(response.user); this.state = 'Authenticated'; this.setupNotificationListener(); callback(null, { response: 'OK', message: Buffer.from(username + ' authenticated').toString('binary') }); } ); } };