Skip to content

[#738] Fix dereferencing an alias that points into another backend#741

Open
vharseko wants to merge 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issue-738-cross-backend-alias
Open

[#738] Fix dereferencing an alias that points into another backend#741
vharseko wants to merge 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issue-738-cross-backend-alias

Conversation

@vharseko

Copy link
Copy Markdown
Member

Fixes #738.

Cause

LocalBackendSearchOperation resolves the backend once, for the original base DN, and caches it in a field. When the base entry turns out to be an alias, processSearch swaps the base DN and re-enters itself, but never re-resolves the backend, so the recursive call asks the backend of the original base DN for a base DN it does not hold. Aliases whose target lives in the same backend work, which is why this went unnoticed since f771315.

Note that the base entry itself is always found: DirectoryServer.getEntry(baseDN) resolves the backend correctly. Only the search that follows goes to the wrong backend — hence the reported oddity that a base search on the alias target succeeds while a search through the alias does not.

Fix

Re-resolve the backend for the aliased DN before recursing. When no backend holds the target, the backend == null check already at the top of processSearch reports NO_SUCH_OBJECT for the new base DN.

Both backends are also made to honour the LocalBackend.search contract when handed a base DN they do not hold — this is what made the bug so hard to read, since neither returned a usable result code:

  • MemoryBackend only reported a missing base entry when handlesEntry() was true, and otherwise went on to match the filter against a null entry, so a base search answered with a NullPointerException from SearchFilter (result 80) and a subtree search with zero entries.
  • The pluggable backend reported UNDEFINED (-1), a result code used internally.

Both now return NO_SUCH_OBJECT. UNDEFINED stays the default for the other accessBegin() callers, since hasSubordinates() relies on it as a sentinel.

Tests

  • AliasTestCase: a second backend (o=test2), an alias crossing the backend boundary (base and subtree scope), and an alias whose target has no backend at all. Only aliases within o=test were covered so far. All three fail without the fix.
  • PluggableBackendImplTestCase: contract test for a base DN held by no entry container, running for JE, PDB, JDBC and Cassandra.
  • MemoryBackendTestCase: new, the memory backend had no test class of its own.

Also run green: OverlappingBackendTestSuite, LocalBackendWorkflowElementTest, GenericLocalBackendTestCase, LDIFBackendTestCase, SearchOperationTestCase, BackendConfigManagerTestCase, InternalClientConnectionTestCase, InternalSearchOperationTestCase, ChangelogBackendTestCase.

…o another backend

LocalBackendSearchOperation resolves the backend once, for the original base DN,
and caches it in a field. When the base entry turns out to be an alias,
processSearch swaps the base DN and re-enters itself, but never re-resolves the
backend, so the recursive call asks the backend of the original base DN for a
base DN it does not hold. Aliases whose target lives in the same backend work,
which is why this went unnoticed since f771315.

Re-resolve the backend for the aliased DN before recursing. When no backend holds
the target, the null check already at the top of processSearch reports
NO_SUCH_OBJECT for the new base DN.

Make both backends honour the LocalBackend.search contract when handed a base DN
they do not hold, which is what made this bug so hard to read: MemoryBackend only
reported a missing base entry when handlesEntry() was true and otherwise went on
to match the filter against a null entry, answering a base search with a
NullPointerException (result 80); the pluggable backend reported the internally
used UNDEFINED (-1). Both now return NO_SUCH_OBJECT. UNDEFINED stays the default
for the other accessBegin() callers: hasSubordinates() relies on it.

Add AliasTestCase coverage for an alias crossing a backend boundary and for an
alias whose target has no backend at all, a contract test to
PluggableBackendImplTestCase, and MemoryBackendTestCase for the memory backend.
@vharseko vharseko requested a review from maximthomas July 15, 2026 13:42
@vharseko vharseko added bug java Pull requests that update java code labels Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug java Pull requests that update java code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant