skip to content

Why would a service check one attribute value with an LDAP Compare rather than a search?

level: middleimportance: nice to knowfreq 24%

answer

  1. a yes or no, not an entry
  2. the answer rides in the result code
  3. you must already know the name
  4. two codes that both mean it worked
  5. comparable is not the same as readable

basics

~20 s

Compare asks one yes-or-no question about one named entry and answers with the resultCode compareTrue(6) or compareFalse(5). It returns no attribute data, so it can confirm a value a caller is not permitted to read and cannot be used to enumerate.

solid answer

~40 s

A Compare request names one entry's Distinguished Name and one attribute-value assertion. The answer arrives as the `resultCode` itself — `compareTrue (6)` or `compareFalse (5)` — and no entry data comes back at all, so the caller learns exactly one bit and nothing more. That has two consequences. First, it cannot enumerate: the caller must already know the Distinguished Name and the value it is testing. Second, access control can permit comparing an attribute that may not be read, which is the classic arrangement for `userPassword`. Note the trap: `success (0)` is never a Compare's answer, so code that treats every non-zero code as a failure reports an error on a perfectly good comparison. A non-existent entry earns `noSuchObject (32)`.

go deeper

for a junior

Recall that Compare answers one yes-or-no question about one named entry, and that the answer arrives as a result code rather than as data.

for a middle

Explain why success (0) is never a Compare's answer, what separates a false comparison from a missing entry, and why the operation cannot be used to enumerate.

for a senior

Show the access-control angle: compare and read are separately grantable, which is why an application can confirm a value it may not retrieve — and why that is still not authentication.

for a principal

Consider where cheap one-bit checks belong in an estate's directory traffic budget, and what it costs in auditability when a question leaves no record of what was read.

## What the operation asks A Compare request carries two things: the Distinguished Name of **one** entry, and an assertion of the form *attribute equals value*. It asks the server a single closed question — does this entry hold this value for this attribute? — and the server answers with a `resultCode`. ## The answer is a code, not data - **`compareTrue (6)`** — the entry holds the asserted value. - **`compareFalse (5)`** — it does not. - **`noSuchObject (32)`** — there is no such entry, which is a different fact from a value that did not match. Nothing else comes back. There is no entry, no attribute list, no values. That is the whole point of the operation, and it produces the trap that catches most client code: **`success (0)` is never the answer to a Compare**. A generic result handler that treats any non-zero `resultCode` as a failure will report an error for a comparison that worked perfectly, and — worse — may report the same error for both possible answers. | operation | answer carried in | data returned | |---|---|---| | Compare | the `resultCode` itself, `compareTrue (6)` or `compareFalse (5)` | none | | a search for the same fact | a result entry, or the absence of one | the attributes that were asked for | ## Why it exists when a search would do Three reasons, and they are the reasons an interviewer is listening for. 1. **It cannot be used to enumerate.** The caller must already know both the Distinguished Name and the value; a caller who knows neither learns nothing. A search, by contrast, is a discovery tool — it takes a pattern and hands back whatever matched. 2. **Compare and read are separately controllable.** A directory can permit an application to *compare* an attribute it may not *read*. `userPassword` is the standard case: an application may confirm a value it was given without being able to retrieve what is stored. 3. **It is cheap for one bit.** Checking whether a Distinguished Name appears in a group entry's `member` values is one assertion evaluated inside the server. Doing it with a search means either transferring thousands of values to the client or constructing a filtered query whose result the client then has to interpret. Whether the assertion matches is decided by the attribute's own equality rules rather than by byte comparison in the client, which is another reason the server is the right place for the question. ## What it is emphatically not A Compare against `userPassword` is **not authentication**. It does not set the connection's authentication state — that is the LDAP Bind operation's job and nothing else's — and a `compareTrue (6)` says only that the assertion matched. Where the server holds a derived form of the value rather than what was originally supplied, an assertion carrying the original need not match at all, so a `compareFalse (5)` is not evidence that the value the caller holds is wrong. Building a login on Compare produces a system that is both insecure in its authorization model and unreliable in its verdicts. ## Reading the result correctly The handling a Compare needs is specific rather than generic: - Map `compareTrue (6)` and `compareFalse (5)` to the two answers, not to success and failure. - Keep `noSuchObject (32)` separate: a wrong name is a different bug from a wrong value, and collapsing the two hides typos in Distinguished Names indefinitely. - Treat `insufficientAccessRights (50)` as its own case: the caller may not even ask this question, which is not the same as the answer being no. ## Where it fits in a consolidation Merging address books, Compare is the cheap pre-flight. Before deleting what looks like a duplicate entry, assert that the surviving entry really does carry the value the duplicate was keeping — the phone number, the staff identifier, the membership — and act on `compareTrue (6)`. One bit, one request, no data moved, and no chance of the check itself leaking an attribute the job was never meant to read.

  • What distinguishes compareFalse (5) from noSuchObject (32)?
    `compareFalse (5)` says an entry exists and does not hold the asserted value; `noSuchObject (32)` says there is no such entry at all. A client that collapses both into 'no' can never tell a wrong value from a wrong Distinguished Name, which is exactly the bug a consolidation job cannot afford.
  • Why is a Compare against a large group entry cheaper than reading its members?
    The server evaluates one assertion under the attribute's own equality rules and returns a verdict in the `resultCode`. Reading the group means transferring every `member` value to the client and comparing there, which costs bandwidth proportional to the group and hands the caller data it did not need.

saying these in an interview costs you the question

  • Expects success (0) when the asserted value matches
  • Treats compareFalse (5) as a protocol error
  • Says a matching Compare on a password authenticates the connection
  • Thinks Compare returns the attribute's actual stored value
  • Uses Compare without already knowing the entry's Distinguished Name
  • Collapses noSuchObject (32) and compareFalse (5) into one outcome