When a directory server refuses an unprotected LDAP simple bind, what does an older client that cannot negotiate TLS receive?
answer
- a result code, not a dead socket
- two codes mean policy, one means password
- confidentiality versus authentication strength
- the server can announce its own hang-up
- retries look exactly like an attack
basics
~20 sA result code, not a dropped socket: confidentialityRequired (13) when the server demands a protected connection, or strongerAuthRequired (8) when it demands stronger authentication. A server may also send an unsolicited Notice of Disconnection before ending the association.
solid answer
~40 sEnforcement shows up as a refused operation with a specific reason. A server that will not accept the name/password authentication mechanism of simple bind on an unprotected connection answers with `confidentialityRequired (13)`; where its policy is that the client must authenticate more strongly, the code is `strongerAuthRequired (8)`. Neither is `invalidCredentials (49)`, and that distinction is the whole diagnosis. A server may also terminate the association, sending the unsolicited `Notice of Disconnection (1.3.6.1.4.1.1466.20036)` first. What breaks is everything whose LDAP stack has no in-band upgrade and no protected-port option — and, worse, every client that reads any bind failure as a bad password and retries, turning a protocol refusal into what looks like a credential storm.
code
pseudocode · 10 lineson BindRequest:
if AuthenticationChoice is simple [0] and password is non-empty:
if the connection has no TLS layer and no SASL security layer:
reply resultCode = confidentialityRequired (13)
return
if policy requires a stronger authentication method here:
reply resultCode = strongerAuthRequired (8)
return
verify the credential
-- a wrong password is invalidCredentials (49), a different answergo deeper
Know that a directory can refuse to accept a password on an unprotected connection, and that it says so with a specific result code rather than by dropping the connection.
Name the codes and what separates them: confidentialityRequired (13) for a missing protected connection, strongerAuthRequired (8) for an insufficient method, invalidCredentials (49) for an actually wrong password.
Show that you have lived the cutover: the retry loop that mimics a credential attack, the long-lived connection that fails days later, the anonymous monitor that never went red, and how you made refused binds visible per client first.
The call is about what you are willing to break and how you will see it. Argue for an inventory of client capability, a measurable refusal signal, and a stated exemption path before the switch rather than after.
## The setting A decommissioning site's contractor badge database makes this concrete: badge readers at every gate, a contractor-vetting service, and a handful of terminals nobody dares replace, all binding to one directory. Someone decides the directory will no longer accept a password on an unprotected connection. The question is not whether that is right — it is what the estate actually sees the morning it takes effect. ## Enforcement is a refusal with a reason The server does not silently drop these clients. It answers the LDAP Bind operation with a result code that says why: | resultCode | What the server is saying | |---|---| | `confidentialityRequired (13)` | this operation needs a protected connection, and this connection has none | | `strongerAuthRequired (8)` | the authentication offered is not strong enough for what policy requires here | | `invalidCredentials (49)` | the name or password is wrong — a different problem entirely | | `unwillingToPerform (53)` | a generic policy refusal that tells the client almost nothing | The first two are the enforcement codes and the third is the one clients wrongly infer. A server may also decide not to keep the association at all: the **`Notice of Disconnection (1.3.6.1.4.1.1466.20036)`** is an unsolicited notification — carried with a `messageID` of zero, so it is a reply to nothing the client sent — that a server emits to say it is about to terminate the association rather than leaving the client to discover a dead connection. ## What actually breaks - **Clients with no upgrade path.** An embedded reader whose LDAP stack implements neither the StartTLS extended operation nor a protected-port connection cannot comply at all. There is no configuration that rescues it; it is replaced or it is exempted. - **Clients that retry.** This is the damaging one. A client that treats every bind failure as a wrong password will re-send, often immediately and often forever. The directory sees a burst of failed binds from a service identity — which looks exactly like a credential attack, and on estates with lockout policies produces a self-inflicted outage. - **Silent fallback.** A client told to attempt the upgrade and continue on failure has been sending passwords in the clear on every refusal all along. Enforcement does not create that exposure; it reveals it. - **Health checks that lie.** Enforcement usually targets the name/password authentication mechanism. A monitor that performs an anonymous bind and reads the `root DSE` keeps reporting green while every real client is refused. - **Readers that never complain.** A component that binds once at boot and holds the connection for weeks will not fail until it reconnects — so the breakage is spread across days, not concentrated on the cutover. ## Diagnosing it from the client side The entire diagnosis is 'which resultCode', and most client logs throw it away. Three checks, in order: 1. Read the actual code. `13` or `8` means the connection or the authentication method was the problem; `49` means the credential was. 2. Read the `diagnosticMessage` beside it — it is free text, but it is the server's own words about this refusal. 3. Establish whether the client ever attempted the upgrade. A client that never sent the StartTLS `ExtendedRequest` is not misconfigured for TLS; it has no TLS. ## The directory-side settings that go with it Refusing unprotected passwords is the first of a family. A directory can also be set to require that the credentials in a bind be **bound to the very protected connection that carries them**, rather than merely arriving over one, and to require integrity protection on the operations that follow. These are server-side switches with the same shape of consequence: a client whose stack cannot produce the binding is refused even though its protected connection was established successfully, and the refusal is indistinguishable from a credential problem in most client logs. They are therefore turned on against an inventory of what each client can actually do, not on a date. ## The judgement to show The protocol part of this answer is short: two result codes and an unsolicited notification. The senior part is knowing that the enforcement is fine and the **failure signal** is the problem — a refusal that every client reports as 'bind failed', a retry loop that impersonates an attack, and a monitor that stays green throughout. Before flipping the switch you want the refused binds visible per client identity, and after it you want a way to tell a policy refusal from a wrong password without reading a packet.
- A directory is additionally set to require that bind credentials be bound to the protected connection carrying them. What changes for existing clients?It adds a second condition beyond 'the connection is protected': the client must produce credentials tied to that specific protected connection. A client whose stack cannot do that is refused even though its connection was established normally, and the refusal looks like a credential failure in its log — so the setting is enabled against a known inventory of client capability rather than on a date.
- Why can a server still be answering searches in the clear after unprotected password binds are refused?Enforcement usually targets the name/password authentication mechanism of simple bind. The anonymous authentication mechanism carries no password, so a server may keep accepting it on an unprotected connection and answering whatever anonymous callers may read — with those entries crossing the network unprotected. Refusing passwords and refusing unprotected reads are two separate decisions.
- How should a client distinguish a protection refusal from a wrong password?By branching on the resultCode rather than on 'the bind failed'. `confidentialityRequired (13)` and `strongerAuthRequired (8)` are policy refusals that no retry will fix and that should raise a configuration alert; `invalidCredentials (49)` is a credential problem where a bounded retry makes sense. The `diagnosticMessage` beside the code usually carries the server's own explanation.
- What is the Notice of Disconnection for, given the server could just close the connection?It is an unsolicited notification that tells the client the association is ending and why, instead of leaving it to infer a cause from a dead connection. That matters for a client that would otherwise retry blindly, and it gives an operator a recorded reason at the moment of the disconnect rather than a silent gap.
saying these in an interview costs you the question
- Assumes a protection refusal arrives as invalidCredentials (49).
- Says the server simply drops the connection with no result code.
- Thinks a green anonymous health check proves clients can still bind.
- Treats retrying a refused bind as harmless rather than lockout-inducing.
- Believes refusing password binds also stops unprotected anonymous reads.