Skip to content

Dereferencing an alias that points into another backend searches the wrong backend #738

Description

@vharseko

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

backend.search(this);

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.

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions