skip to content

In LDAPv3, how does a Control attached to a request differ from an extended operation?

level: juniorimportance: must knowfreq 46%

answer

  1. two shapes, not one
  2. one rides along, one stands alone
  3. controlType, criticality, controlValue
  4. requestName answered by ExtendedResponse
  5. root DSE lists both separately

basics

~20 s

An LDAP Control rides along on a request the protocol already defines and changes how the server carries it out. An extended operation is a whole new request, named by its own OID, that the base operation set never had.

solid answer

~40 s

LDAPv3 is a closed set of operations, so it grew two ways of adding behaviour without a new protocol version. A **Control** is a small `SEQUENCE` of `controlType` (an OID), `criticality` and an optional `controlValue`, carried in the request's `Controls` field; it never travels alone, it modifies an operation that already exists — simple paged results (1.2.840.113556.1.4.319) on a `SearchRequest`, for example. An **extended operation** is its own `ExtendedRequest` with a `requestName` OID and an optional `requestValue`, answered by an `ExtendedResponse`; Password Modify (1.3.6.1.4.1.4203.1.11.1) and StartTLS (1.3.6.1.4.1.1466.20037) are two. A server advertises what it holds in the root DSE, under `supportedControl` and `supportedExtension` respectively.

code

asn1 · 8 lines
asn1
Control ::= SEQUENCE {
    controlType     LDAPOID,
    criticality     BOOLEAN DEFAULT FALSE,
    controlValue    OCTET STRING OPTIONAL }

ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
    requestName     [0] LDAPOID,
    requestValue    [1] OCTET STRING OPTIONAL }

go deeper

for a junior

Recall that LDAPv3 cannot grow new operation codes, so behaviour is added either as a Control riding on an existing request or as an extended operation with its own OID. Name one example of each.

for a middle

Explain the field-by-field shape: controlType, criticality and controlValue against requestName and requestValue, and why the root DSE advertises the two in separate attributes rather than one list.

for a senior

Show the judgment: choose the control shape when a client can still use a result without the behaviour, and the extended-operation shape when it cannot, then check the root DSE per server rather than per cluster.

for a principal

Frame it as an interface-evolution question — a frozen verb set with a registered-OID escape hatch keeps every old client working while letting servers diverge, at the cost of capability discovery becoming a runtime concern.

## Why a directory protocol needs an extension mechanism at all LDAPv3, as specified in `RFC 4511`, defines a fixed and deliberately small set of protocol operations: the LDAP Bind operation and `UnbindRequest`, `SearchRequest`, `ModifyRequest`, `AddRequest`, `DelRequest`, `ModifyDNRequest`, `CompareRequest`, `AbandonRequest` and `ExtendedRequest`. That list has not grown in decades. Everything a directory server has learned to do since — returning a huge result set in pages, ordering it, changing a password safely, telling a client which identity its connection currently holds — arrived through extension rather than through a new operation code or a version bump. Two mechanisms carry almost all of that, and they are not interchangeable. ## An LDAP Control rides on an operation that already exists A Control is a small structure carried in the `Controls` field of the `LDAPMessage` envelope, so any request can carry any number of them: - `controlType` — the OID that names the control; - `criticality` — a `BOOLEAN DEFAULT FALSE` saying whether the server may proceed without honouring it; - `controlValue` — an optional `OCTET STRING` holding whatever parameters that control defines. A Control is always a modifier. It cannot be sent on its own, it has no result of its own, and it only makes sense against the operation it is attached to. Examples across the family: - simple paged results (1.2.840.113556.1.4.319) on a `SearchRequest`, asking for the result set a page at a time; - the server-side sorting request (1.2.840.113556.1.4.473), asking for that result set in a defined order; - the Assertion Control (1.3.6.1.1.12), making a write conditional on the directory entry still matching a condition; - the Pre-Read Control (1.3.6.1.1.13.1) and Post-Read Control (1.3.6.1.1.13.2), returning a copy of the directory entry as it was just before, or just after, the write; - the Subentries Control (1.3.6.1.4.1.4203.1.10.1), changing which entries a search considers. Notice that none of these is a new thing to ask for. Each one changes how an existing Search or Modify is carried out. ## An extended operation is a request the base protocol never had An `ExtendedRequest` carries a `requestName` — the OID that says which operation this is — and an optional `requestValue` holding its parameters. The server answers with an `ExtendedResponse`. Because the operation is defined entirely by that OID, the protocol can gain genuinely new verbs without touching its grammar: - Password Modify (1.3.6.1.4.1.4203.1.11.1), which changes a stored credential without the client writing to an attribute by hand; - "Who am I?" (1.3.6.1.4.1.4203.1.11.3), which asks the server which authorization identity this connection currently holds; - Cancel (1.3.6.1.1.8), which asks for an outstanding operation to be stopped and — unlike `AbandonRequest`, which has no response at all — tells the client what happened; - StartTLS (1.3.6.1.4.1.1466.20037), which negotiates protection on an already-open connection. There is a third message shape worth knowing: `IntermediateResponse`, which a server may send between the request and its final response. It lets a long-running or extended operation report progress without ending. And there is a smaller third extension route: a **feature OID**, advertised in the root DSE's `supportedFeatures`, which announces a new value inside an existing request rather than a new request or a new modifier. Modify-Increment (1.3.6.1.1.14), which adds `increment (3)` alongside `add (0)`, `delete (1)` and `replace (2)` in a `ModifyRequest`, is the standard example. ## The two shapes side by side | | Control | Extended operation | |---|---|---| | carried as | a member of an existing request's `Controls` | its own `ExtendedRequest` | | named by | `controlType` | `requestName` | | parameters in | `controlValue` | `requestValue` | | may the server ignore it? | yes, when `criticality` is FALSE | no — it is the whole request | | advertised in the root DSE as | `supportedControl` | `supportedExtension` | | what it is for | changing how an operation behaves | doing something no operation covers | ## How to tell which shape a new feature should take 1. Ask whether an existing operation already does the job and only needs steering. Paging and sorting steer a search that would otherwise work; both are controls. 2. Ask whether the client needs an answer that is not an operation's normal result. "Who am I?" has no host operation to ride on; it is an extended operation. 3. Ask whether a client that does not get the behaviour can still use the result. If it can, a non-critical control is the graceful shape; if it cannot, the feature needs to fail visibly, which an extended operation does by construction. ## Why this matters before you write a line of directory code Suppose an equipment-booking system at a research institute needs every member of groups that run to tens of thousands of directory entries, in a stable order, and needs to reset a departing researcher's stored credential. Those are three jobs the base operation set cannot do — and they are reached through **both** mechanisms: two controls on a `SearchRequest`, and one extended operation. A developer who knows only "LDAP has a search" writes a loop that silently stops at the server's own limit. Knowing there are two extension shapes, and that the root DSE will tell you which ones this server actually holds, is the difference.

  • How does a client find out which LDAP Controls and extended operations a given directory server supports?
    It reads the root DSE — a search with `baseObject` scope from a zero-length base DN — and looks at `supportedControl` and `supportedExtension`, each a multi-valued list of OIDs. `supportedFeatures` covers the third kind, such as Modify-Increment (1.3.6.1.1.14). This is per server, so a pool of replicas can answer differently.
  • What is an IntermediateResponse for, if the operation already has a final response?
    It is a third message shape a server may send between a request and its final result, so a long-running or extended operation can hand back something before it finishes. The operation is still open; the client must keep reading until the final response arrives.
  • Why is Cancel (1.3.6.1.1.8) an extended operation when AbandonRequest already exists?
    `AbandonRequest` is fire-and-forget: it has no response, so the client never learns whether the operation stopped, finished, or was never seen. Cancel is a request with an answer, which is what a client needs when it must know the state it left the server in.

A Control is an instruction written on an order form you were already sending — 'leave it with a neighbour'. An extended operation is a different form altogether, for something the original form has no box for.

saying these in an interview costs you the question

  • Says every LDAP extension is a new operation
  • Thinks a Control can be sent without a base operation
  • Believes a server must implement every control it receives
  • Confuses an LDAP Control with an access-control entry on a directory entry
  • Assumes extended operations need a different port or protocol version