Improve empty DN handling

- Use more strict comparisons for client input asserts
- Fix baseObject comparison in SearchRequest initialization
- Alter default error for server route fallthrough
This commit is contained in:
Patrick Mooney 2015-04-25 20:53:50 -05:00
parent 19f2c16783
commit ec062d370c
4 changed files with 60 additions and 10 deletions

View File

@ -407,7 +407,7 @@ Client.prototype.abandon = function abandon(messageID, controls, callback) {
* @throws {TypeError} on invalid input. * @throws {TypeError} on invalid input.
*/ */
Client.prototype.add = function add(name, entry, controls, callback) { Client.prototype.add = function add(name, entry, controls, callback) {
assert.ok(name, 'name'); assert.ok(name !== undefined, 'name');
assert.object(entry, 'entry'); assert.object(entry, 'entry');
if (typeof (controls) === 'function') { if (typeof (controls) === 'function') {
callback = controls; callback = controls;
@ -500,7 +500,7 @@ Client.prototype.compare = function compare(name,
value, value,
controls, controls,
callback) { callback) {
assert.ok(name, 'name'); assert.ok(name !== undefined, 'name');
assert.string(attr, 'attr'); assert.string(attr, 'attr');
assert.string(value, 'value'); assert.string(value, 'value');
if (typeof (controls) === 'function') { if (typeof (controls) === 'function') {
@ -536,7 +536,7 @@ Client.prototype.compare = function compare(name,
* @throws {TypeError} on invalid input. * @throws {TypeError} on invalid input.
*/ */
Client.prototype.del = function del(name, controls, callback) { Client.prototype.del = function del(name, controls, callback) {
assert.ok(name, 'name'); assert.ok(name !== undefined, 'name');
if (typeof (controls) === 'function') { if (typeof (controls) === 'function') {
callback = controls; callback = controls;
controls = []; controls = [];
@ -609,7 +609,7 @@ Client.prototype.exop = function exop(name, value, controls, callback) {
* @throws {TypeError} on invalid input. * @throws {TypeError} on invalid input.
*/ */
Client.prototype.modify = function modify(name, change, controls, callback) { Client.prototype.modify = function modify(name, change, controls, callback) {
assert.ok(name, 'name'); assert.ok(name !== undefined, 'name');
assert.object(change, 'change'); assert.object(change, 'change');
var changes = []; var changes = [];
@ -691,7 +691,7 @@ Client.prototype.modifyDN = function modifyDN(name,
newName, newName,
controls, controls,
callback) { callback) {
assert.ok(name, 'name'); assert.ok(name !== undefined, 'name');
assert.string(newName, 'newName'); assert.string(newName, 'newName');
if (typeof (controls) === 'function') { if (typeof (controls) === 'function') {
callback = controls; callback = controls;
@ -750,7 +750,7 @@ Client.prototype.search = function search(base,
controls, controls,
callback, callback,
_bypass) { _bypass) {
assert.ok(base, 'base'); assert.ok(base !== undefined, 'search base');
if (Array.isArray(options) || (options instanceof Control)) { if (Array.isArray(options) || (options instanceof Control)) {
controls = options; controls = options;
options = {}; options = {};

View File

@ -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.scope = options.scope || 'base';
this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES; this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES;
this.sizeLimit = options.sizeLimit || 0; this.sizeLimit = options.sizeLimit || 0;

View File

@ -867,6 +867,9 @@ Server.prototype._getHandlerChain = function _getHandlerChain(req, res) {
backend: route.backend, backend: route.backend,
handlers: route[op] handlers: route[op]
}; };
} else {
if (suffix === '') {
break;
} else { } else {
// We found a valid suffix but not a valid operation. // We found a valid suffix but not a valid operation.
// There might be a more generic suffix with a legitimate operation. // There might be a more generic suffix with a legitimate operation.
@ -874,6 +877,7 @@ Server.prototype._getHandlerChain = function _getHandlerChain(req, res) {
} }
} }
} }
}
return { return {
backend: self, backend: self,
handlers: fallbackHandler handlers: fallbackHandler

View File

@ -231,6 +231,23 @@ test('setup', function (t) {
next(new ldap.BusyError('too much to do')); 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) { server.unbind(function (req, res, next) {
res.end(); res.end();
return next(); return next();
@ -274,6 +291,7 @@ test('simple bind success', function (t) {
}); });
}); });
test('simple anonymous bind (empty credentials)', function (t) { test('simple anonymous bind (empty credentials)', function (t) {
client.bind('', '', function (err, res) { client.bind('', '', function (err, res) {
t.ifError(err); t.ifError(err);
@ -283,6 +301,7 @@ test('simple anonymous bind (empty credentials)', function (t) {
}); });
}); });
test('auto-bind bad credentials', function (t) { test('auto-bind bad credentials', function (t) {
var clt = ldap.createClient({ var clt = ldap.createClient({
socketPath: SOCKET, 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) { test('search empty attribute', function (t) {
client.search('dc=empty', '(objectclass=*)', function (err, res) { client.search('dc=empty', '(objectclass=*)', function (err, res) {
t.ifError(err); t.ifError(err);