Skip to content

sources/ldap: derive TLS SNI name from hostname, not full server URI#22456

Open
ramazanpolat wants to merge 2 commits into
goauthentik:mainfrom
ramazanpolat:fix/ldap-source-sni-hostname
Open

sources/ldap: derive TLS SNI name from hostname, not full server URI#22456
ramazanpolat wants to merge 2 commits into
goauthentik:mainfrom
ramazanpolat:fix/ldap-source-sni-hostname

Conversation

@ramazanpolat
Copy link
Copy Markdown

Details

LDAPSource.server() builds the TLS SNI server name from the raw server_uri:

if self.sni:
    tls_kwargs["sni"] = self.server_uri.split(",", maxsplit=1)[0].strip()

server_uri is a full LDAP URI (e.g. ldaps://ldap.example.com).
.split(",")[0].strip() only handles the comma-separated multi-server case and
trims whitespace — it does not strip the ldap:// / ldaps:// scheme or a
:port. The resulting value is passed as Tls(sni=...), which ldap3 forwards
as server_hostname to Python's ssl module.

A TLS SNI name must be a bare DNS hostname. Sending ldaps://ldap.example.com
as the SNI name causes SNI-strict servers / load balancers (common for TLS 1.3
load-balanced endpoints) to drop the handshake, so every LDAP sync and the
connectivity check fail with:

LDAPSocketOpenError: socket ssl wrapping error:
[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol

This makes the "Use Server URI for SNI verification" toggle strictly worse than
leaving it off for any such endpoint.

Fix

Build each Server first and derive the SNI name from server.host — the
hostname ldap3 has already parsed out of the URI (scheme and port stripped).
This also addresses a related point raised in #7756: every server in a
ServerPool previously shared the first server's raw URI as its SNI name;
each server now gets its own correct SNI name.

Verified against ldap3 2.9.1 — Server(uri).host strips ldap:// / ldaps://
and :port for host, host:port, ldap://host, ldaps://host, and
ldaps://host:port.

closes #7756


Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

`LDAPSource.server()` built the TLS SNI server name from the raw
`server_uri`, so an `ldaps://host` URI produced an SNI name of
`ldaps://host` instead of the bare hostname `host`. ldap3 forwards
that as `server_hostname` to the `ssl` module, and SNI-strict servers
drop the handshake -- every LDAP sync and the connectivity check fail
with `SSL: UNEXPECTED_EOF_WHILE_READING`.

Build each `Server` first and take the SNI name from `server.host`,
the hostname ldap3 has already parsed out of the URI (scheme and port
stripped). Each server in a pool now gets its own SNI name instead of
all sharing the first server's raw URI.

closes goauthentik#7756

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented May 19, 2026

Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit e705df5
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/6a0bbbb9dca569000862137b
😎 Deploy Preview https://deploy-preview-22456--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LDAP Source URI is parsed incorrectly which leads to invalid SNI configuration

1 participant