diff --git a/lib/client/client.js b/lib/client/client.js index f90dc82..b18a441 100644 --- a/lib/client/client.js +++ b/lib/client/client.js @@ -407,7 +407,7 @@ Client.prototype.abandon = function abandon(messageID, controls, callback) { * @throws {TypeError} on invalid input. */ Client.prototype.add = function add(name, entry, controls, callback) { - assert.ok(name, 'name'); + assert.ok(name !== undefined, 'name'); assert.object(entry, 'entry'); if (typeof (controls) === 'function') { callback = controls; @@ -500,7 +500,7 @@ Client.prototype.compare = function compare(name, value, controls, callback) { - assert.ok(name, 'name'); + assert.ok(name !== undefined, 'name'); assert.string(attr, 'attr'); assert.string(value, 'value'); if (typeof (controls) === 'function') { @@ -536,7 +536,7 @@ Client.prototype.compare = function compare(name, * @throws {TypeError} on invalid input. */ Client.prototype.del = function del(name, controls, callback) { - assert.ok(name, 'name'); + assert.ok(name !== undefined, 'name'); if (typeof (controls) === 'function') { callback = controls; controls = []; @@ -609,7 +609,7 @@ Client.prototype.exop = function exop(name, value, controls, callback) { * @throws {TypeError} on invalid input. */ Client.prototype.modify = function modify(name, change, controls, callback) { - assert.ok(name, 'name'); + assert.ok(name !== undefined, 'name'); assert.object(change, 'change'); var changes = []; @@ -691,7 +691,7 @@ Client.prototype.modifyDN = function modifyDN(name, newName, controls, callback) { - assert.ok(name, 'name'); + assert.ok(name !== undefined, 'name'); assert.string(newName, 'newName'); if (typeof (controls) === 'function') { callback = controls; @@ -750,7 +750,7 @@ Client.prototype.search = function search(base, controls, callback, _bypass) { - assert.ok(base, 'base'); + assert.ok(base !== undefined, 'search base'); if (Array.isArray(options) || (options instanceof Control)) { controls = options; options = {}; diff --git a/lib/messages/search_request.js b/lib/messages/search_request.js index d78d8f2..d68f5b9 100644 --- a/lib/messages/search_request.js +++ b/lib/messages/search_request.js @@ -64,7 +64,11 @@ function SearchRequest(options) { } }); - this.baseObject = options.baseObject || new DN([ {} ]); + if (options.baseObject !== undefined) { + this.baseObject = options.baseObject; + } else { + this.baseObject = dn.parse(''); + } this.scope = options.scope || 'base'; this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES; this.sizeLimit = options.sizeLimit || 0; diff --git a/lib/server.js b/lib/server.js index 271f770..84984d0 100644 --- a/lib/server.js +++ b/lib/server.js @@ -868,9 +868,13 @@ Server.prototype._getHandlerChain = function _getHandlerChain(req, res) { handlers: route[op] }; } else { - // We found a valid suffix but not a valid operation. - // There might be a more generic suffix with a legitimate operation. - fallbackHandler = [defaultHandler]; + if (suffix === '') { + break; + } else { + // We found a valid suffix but not a valid operation. + // There might be a more generic suffix with a legitimate operation. + fallbackHandler = [defaultHandler]; + } } } } diff --git a/test/client.test.js b/test/client.test.js index ca38f53..2c016c5 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -231,6 +231,23 @@ test('setup', function (t) { next(new ldap.BusyError('too much to do')); }); + server.search('', function (req, res, next) { + if (req.dn.toString() === '') { + res.send({ + dn: '', + attributes: { + objectclass: ['RootDSE', 'top'] + } + }); + res.end(); + } else { + // Turn away any other requests (since '' is the fallthrough route) + res.errorMessage = 'No tree found for: ' + req.dn.toString(); + res.end(ldap.LDAP_NO_SUCH_OBJECT); + } + return next(); + }); + server.unbind(function (req, res, next) { res.end(); return next(); @@ -274,6 +291,7 @@ test('simple bind success', function (t) { }); }); + test('simple anonymous bind (empty credentials)', function (t) { client.bind('', '', function (err, res) { t.ifError(err); @@ -283,6 +301,7 @@ test('simple anonymous bind (empty credentials)', function (t) { }); }); + test('auto-bind bad credentials', function (t) { var clt = ldap.createClient({ socketPath: SOCKET, @@ -710,6 +729,29 @@ test('search referral', function (t) { }); +test('search rootDSE', function (t) { + client.search('', '(objectclass=*)', function (err, res) { + t.ifError(err); + t.ok(res); + res.on('searchEntry', function (entry) { + t.ok(entry); + t.equal(entry.dn.toString(), ''); + t.ok(entry.attributes); + t.ok(entry.object); + }); + res.on('error', function (err) { + t.fail(err); + }); + res.on('end', function (res) { + t.ok(res); + t.ok(res instanceof ldap.SearchResponse); + t.equal(res.status, 0); + t.end(); + }); + }); +}); + + test('search empty attribute', function (t) { client.search('dc=empty', '(objectclass=*)', function (err, res) { t.ifError(err);