diff --git a/src/boxerror.js b/src/boxerror.js index 9d32b6a3d..c52de2ea1 100644 --- a/src/boxerror.js +++ b/src/boxerror.js @@ -45,6 +45,7 @@ BoxError.EXTERNAL_ERROR = 'External Error'; // use this for external API errors BoxError.FS_ERROR = 'FileSystem Error'; BoxError.INACTIVE = 'Inactive'; BoxError.INTERNAL_ERROR = 'Internal Error'; +BoxError.INVALID_CREDENTIALS = 'Invalid Credentials'; BoxError.LICENSE_ERROR = 'License Error'; BoxError.LOGROTATE_ERROR = 'Logrotate Error'; BoxError.NETWORK_ERROR = 'Network Error'; diff --git a/src/externalldap.js b/src/externalldap.js index 48fbe246b..faa305681 100644 --- a/src/externalldap.js +++ b/src/externalldap.js @@ -1,8 +1,6 @@ 'use strict'; exports = module.exports = { - ExternalLdapError: ExternalLdapError, - verifyPassword: verifyPassword, testConfig: testConfig, @@ -14,62 +12,36 @@ exports = module.exports = { var assert = require('assert'), async = require('async'), auditsource = require('./auditsource.js'), + BoxError = require('./boxerror.js'), debug = require('debug')('box:externalldap'), ldap = require('ldapjs'), settings = require('./settings.js'), tasks = require('./tasks.js'), users = require('./users.js'), - UserError = users.UsersError, - util = require('util'); - -function ExternalLdapError(reason, errorOrMessage) { - assert.strictEqual(typeof reason, 'string'); - assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined'); - - Error.call(this); - Error.captureStackTrace(this, this.constructor); - - this.name = this.constructor.name; - this.reason = reason; - if (typeof errorOrMessage === 'undefined') { - this.message = reason; - } else if (typeof errorOrMessage === 'string') { - this.message = errorOrMessage; - } else { - this.message = 'Internal error'; - this.nestedError = errorOrMessage; - } -} -util.inherits(ExternalLdapError, Error); -ExternalLdapError.EXTERNAL_ERROR = 'external error'; -ExternalLdapError.INTERNAL_ERROR = 'internal error'; -ExternalLdapError.INVALID_CREDENTIALS = 'invalid credentials'; -ExternalLdapError.BAD_STATE = 'bad state'; -ExternalLdapError.BAD_FIELD = 'bad field'; -ExternalLdapError.NOT_FOUND = 'not found'; + UserError = users.UsersError; // performs service bind if required function getClient(externalLdapConfig, callback) { assert.strictEqual(typeof callback, 'function'); // basic validation to not crash - try { ldap.parseDN(externalLdapConfig.baseDn); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'invalid baseDn')); } - try { ldap.parseFilter(externalLdapConfig.filter); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'invalid filter')); } - if (externalLdapConfig.bindDn) try { ldap.parseFilter(externalLdapConfig.bindDn); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS)); } + try { ldap.parseDN(externalLdapConfig.baseDn); } catch (e) { return callback(new BoxError(BoxError.BAD_FIELD, 'invalid baseDn')); } + try { ldap.parseFilter(externalLdapConfig.filter); } catch (e) { return callback(new BoxError(BoxError.BAD_FIELD, 'invalid filter')); } + if (externalLdapConfig.bindDn) try { ldap.parseFilter(externalLdapConfig.bindDn); } catch (e) { return callback(new BoxError(BoxError.INVALID_CREDENTIALS)); } var client; try { client = ldap.createClient({ url: externalLdapConfig.url }); } catch (e) { - if (e instanceof ldap.ProtocolError) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'url protocol is invalid')); - return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, e)); + if (e instanceof ldap.ProtocolError) return callback(new BoxError(BoxError.BAD_FIELD, 'url protocol is invalid')); + return callback(new BoxError(BoxError.INTERNAL_ERROR, e)); } if (!externalLdapConfig.bindDn) return callback(null, client); client.bind(externalLdapConfig.bindDn, externalLdapConfig.bindPassword, function (error) { - if (error instanceof ldap.InvalidCredentialsError) return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS)); - if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error)); + if (error instanceof ldap.InvalidCredentialsError) return callback(new BoxError(BoxError.INVALID_CREDENTIALS)); + if (error) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error)); callback(null, client, externalLdapConfig); }); @@ -81,9 +53,9 @@ function testConfig(config, callback) { if (!config.enabled) return callback(); - if (!config.url) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'url must not be empty')); - if (!config.baseDn) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'basedn must not be empty')); - if (!config.filter) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'filter must not be empty')); + if (!config.url) return callback(new BoxError(BoxError.BAD_FIELD, 'url must not be empty')); + if (!config.baseDn) return callback(new BoxError(BoxError.BAD_FIELD, 'basedn must not be empty')); + if (!config.filter) return callback(new BoxError(BoxError.BAD_FIELD, 'filter must not be empty')); getClient(config, function (error, client) { if (error) return callback(error); @@ -94,10 +66,10 @@ function testConfig(config, callback) { }; client.search(config.baseDn, opts, function (error, result) { - if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error)); + if (error) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error)); result.on('searchEntry', function (/* entry */) {}); - result.on('error', function (error) { callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, `Unable to search directory: ${error.message}`)); }); + result.on('error', function (error) { callback(new BoxError(BoxError.BAD_FIELD, `Unable to search directory: ${error.message}`)); }); result.on('end', function (/* result */) { callback(); }); }); }); @@ -109,8 +81,8 @@ function verifyPassword(user, password, callback) { assert.strictEqual(typeof callback, 'function'); settings.getExternalLdapConfig(function (error, externalLdapConfig) { - if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error)); - if (!externalLdapConfig.enabled) return callback(new ExternalLdapError(ExternalLdapError.BAD_STATE, 'not enabled')); + if (error) return callback(new BoxError(BoxError.INTERNAL_ERROR, error)); + if (!externalLdapConfig.enabled) return callback(new BoxError(BoxError.BAD_STATE, 'not enabled')); getClient(externalLdapConfig, function (error, client) { if (error) return callback(error); @@ -118,8 +90,8 @@ function verifyPassword(user, password, callback) { const dn = `uid=${user.username},${externalLdapConfig.baseDn}`; client.bind(dn, password, function (error) { - if (error instanceof ldap.InvalidCredentialsError) return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS)); - if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error)); + if (error instanceof ldap.InvalidCredentialsError) return callback(new BoxError(BoxError.INVALID_CREDENTIALS)); + if (error) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error)); callback(); }); @@ -131,11 +103,11 @@ function startSyncer(callback) { assert.strictEqual(typeof callback, 'function'); settings.getExternalLdapConfig(function (error, externalLdapConfig) { - if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error)); - if (!externalLdapConfig.enabled) return callback(new ExternalLdapError(ExternalLdapError.BAD_STATE, 'not enabled')); + if (error) return callback(new BoxError(BoxError.INTERNAL_ERROR, error)); + if (!externalLdapConfig.enabled) return callback(new BoxError(BoxError.BAD_STATE, 'not enabled')); tasks.add(tasks.TASK_SYNC_EXTERNAL_LDAP, [], function (error, taskId) { - if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error)); + if (error) return callback(new BoxError(BoxError.INTERNAL_ERROR, error)); tasks.startTask(taskId, {}, function (error, result) { debug('sync: done', error, result); @@ -153,8 +125,8 @@ function sync(progressCallback, callback) { debug('Start user syncing ...'); settings.getExternalLdapConfig(function (error, externalLdapConfig) { - if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error)); - if (!externalLdapConfig.enabled) return callback(new ExternalLdapError(ExternalLdapError.BAD_STATE, 'not enabled')); + if (error) return callback(new BoxError(BoxError.INTERNAL_ERROR, error)); + if (!externalLdapConfig.enabled) return callback(new BoxError(BoxError.BAD_STATE, 'not enabled')); getClient(externalLdapConfig, function (error, client) { if (error) return callback(error); @@ -168,7 +140,7 @@ function sync(progressCallback, callback) { debug(`Listing users at ${externalLdapConfig.baseDn} with filter ${externalLdapConfig.filter}`); client.search(externalLdapConfig.baseDn, opts, function (error, result) { - if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error)); + if (error) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error)); var ldapUsers = []; @@ -177,11 +149,11 @@ function sync(progressCallback, callback) { }); result.on('error', function (error) { - callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error)); + callback(new BoxError(BoxError.EXTERNAL_ERROR, error)); }); result.on('end', function (result) { - if (result.status !== 0) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, 'Server returned status ' + result.status)); + if (result.status !== 0) return callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Server returned status ' + result.status)); debug(`Found ${ldapUsers.length} users`); diff --git a/src/ldap.js b/src/ldap.js index 1d2747fa9..085b379df 100644 --- a/src/ldap.js +++ b/src/ldap.js @@ -9,8 +9,8 @@ var assert = require('assert'), appdb = require('./appdb.js'), apps = require('./apps.js'), async = require('async'), - constants = require('./constants.js'), BoxError = require('./boxerror.js'), + constants = require('./constants.js'), debug = require('debug')('box:ldap'), eventlog = require('./eventlog.js'), ldap = require('ldapjs'), diff --git a/src/settings.js b/src/settings.js index 2c574ceaa..fabdde54f 100644 --- a/src/settings.js +++ b/src/settings.js @@ -102,7 +102,6 @@ var addons = require('./addons.js'), debug = require('debug')('box:settings'), docker = require('./docker.js'), externalldap = require('./externalldap.js'), - ExternalLdapError = externalldap.ExternalLdapError, moment = require('moment-timezone'), paths = require('./paths.js'), safe = require('safetydance'), @@ -414,10 +413,7 @@ function setExternalLdapConfig(externalLdapConfig, callback) { assert.strictEqual(typeof callback, 'function'); externalldap.testConfig(externalLdapConfig, function (error) { - if (error && error.reason === ExternalLdapError.BAD_FIELD) return callback(new BoxError(BoxError.BAD_FIELD, error.message)); - if (error && error.reason === ExternalLdapError.EXTERNAL_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message)); - if (error && error.reason === ExternalLdapError.INVALID_CREDENTIALS) return callback(new BoxError(BoxError.BAD_FIELD, 'invalid bind credentials')); - if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); + if (error) return callback(error); settingsdb.set(exports.EXTERNAL_LDAP_KEY, JSON.stringify(externalLdapConfig), function (error) { if (error) return callback(error); diff --git a/src/users.js b/src/users.js index 0c72b1d5b..12f268168 100644 --- a/src/users.js +++ b/src/users.js @@ -41,7 +41,6 @@ let assert = require('assert'), DatabaseError = require('./databaseerror.js'), eventlog = require('./eventlog.js'), externalldap = require('./externalldap.js'), - ExternalLdapError = externalldap.ExternalLdapError, groups = require('./groups.js'), hat = require('./hat.js'), mailer = require('./mailer.js'), @@ -256,7 +255,7 @@ function verify(userId, password, callback) { if (user.source === 'ldap') { externalldap.verifyPassword(user, password, function (error) { - if (error && error.reason === ExternalLdapError.INVALID_CREDENTIALS) return callback(new UsersError(UsersError.WRONG_PASSWORD)); + if (error && error.reason === BoxError.INVALID_CREDENTIALS) return callback(new UsersError(UsersError.WRONG_PASSWORD)); if (error) return callback(new UsersError(UsersError.INTERNAL_ERROR, error)); callback(null, user);