Version: 5.1.1, also present on master.
Summary
When a search base is an alias pointing into a different backend, dereferencing it searches the original backend under the aliased DN, instead of the backend that actually holds the alias target. The search returns no such object / no entries, even though a base search on the aliased DN directly succeeds.
Aliases whose target lives in the same backend work fine, which is why this went unnoticed.
Cause
LocalBackendSearchOperation resolves the backend once, for the original base DN, and caches it in a field:
opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendSearchOperation.java#L97-L100
public void processLocalSearch(LocalBackend<?> backend)
{
this.backend = backend;
When the base entry turns out to be an alias, processSearch swaps the base DN and re-enters itself:
opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendSearchOperation.java#L213-L228
final Entry baseEntry=DirectoryServer.getEntry(baseDN);
if (baseEntry!=null && baseEntry.isAlias()) {
final DN aliasedDn = baseEntry.getAliasedDN();
if(!dereferencingDNs.contains(aliasedDn)) { //detect recursive search
dereferencingDNs.add(aliasedDn);
setBaseDN(aliasedDn);
try {
processSearch(executePostOpPlugins);
setBaseDN is a plain field setter (SearchOperationBasis#L319-L322) and processSearch never re-resolves backend, so the recursive call still ends up at the backend picked for the original base DN:
opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendSearchOperation.java#L255
The backend is then asked to search a base DN it does not hold.
Steps to reproduce
With two backends, e.g. o=backend1 and o=backend2, and an alias in the first pointing at an entry in the second:
dn: ou=alias,o=backend1
objectClass: top
objectClass: alias
objectClass: extensibleObject
ou: alias
aliasedObjectName: ou=people,o=backend2
# returns nothing / no such object
ldapsearch -h localhost -p 1389 -D "cn=Directory Manager" -w password \
-b "ou=alias,o=backend1" -s sub -a always "(objectclass=*)"
# the alias target itself is readable
ldapsearch -h localhost -p 1389 -D "cn=Directory Manager" -w password \
-b "ou=people,o=backend2" -s sub -a never "(objectclass=*)"
Regression
Introduced with the alias dereferencing feature in f771315 ("[#287] ADD alias dereferencing for search requests", #369, 2024-08-07). AliasTestCase only covers aliases within a single backend (o=test), so the cross-backend path is untested.
Suggested fix
Re-resolve the backend for the new base DN before recursing, e.g. via BackendConfigManager.findLocalBackendForEntry(aliasedDn), and fail with the usual NO_SUCH_OBJECT when no backend holds it. Worth adding an AliasTestCase case with an alias crossing a backend boundary.
Note
Found while analysing #737, which is a different failure in the same base-entry lookup.
Version: 5.1.1, also present on
master.Summary
When a search base is an alias pointing into a different backend, dereferencing it searches the original backend under the aliased DN, instead of the backend that actually holds the alias target. The search returns no such object / no entries, even though a base search on the aliased DN directly succeeds.
Aliases whose target lives in the same backend work fine, which is why this went unnoticed.
Cause
LocalBackendSearchOperationresolves the backend once, for the original base DN, and caches it in a field:opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendSearchOperation.java#L97-L100When the base entry turns out to be an alias,
processSearchswaps the base DN and re-enters itself:opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendSearchOperation.java#L213-L228setBaseDNis a plain field setter (SearchOperationBasis#L319-L322) andprocessSearchnever re-resolvesbackend, so the recursive call still ends up at the backend picked for the original base DN:opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendSearchOperation.java#L255The backend is then asked to search a base DN it does not hold.
Steps to reproduce
With two backends, e.g.
o=backend1ando=backend2, and an alias in the first pointing at an entry in the second:Regression
Introduced with the alias dereferencing feature in f771315 ("[#287] ADD alias dereferencing for search requests", #369, 2024-08-07).
AliasTestCaseonly covers aliases within a single backend (o=test), so the cross-backend path is untested.Suggested fix
Re-resolve the backend for the new base DN before recursing, e.g. via
BackendConfigManager.findLocalBackendForEntry(aliasedDn), and fail with the usualNO_SUCH_OBJECTwhen no backend holds it. Worth adding anAliasTestCasecase with an alias crossing a backend boundary.Note
Found while analysing #737, which is a different failure in the same base-entry lookup.