Hi Michał, hi all,

back in May I sent a small patch series adding server-side STARTTLS support for the LDAP protocol handler (RFC 2830) — see „[PATCH 0/3] LDAP server-side STARTTLS support“ from 13 May 2026 (quoted below). It was branched off 5.78.

I saw that 5.79 and 5.80 have been released in the meantime. Since 5.80 was a security release addressing two CVEs, I completely understand that the focus was elsewhere — so no pressure at all.

I just wanted to gently follow up: is LDAP server-side STARTTLS something you would consider for a future (normal-urgency) release? I'd just like to know whether it's worth pursuing.

I do think it would be useful beyond our own setup: terminating STARTTLS in front of a plain LDAP backend is a fairly common deployment pattern. STARTTLS (RFC 2830) is the standards-track way to secure LDAP on the regular port — as opposed to LDAPS (TLS-on-connect on 636) — and since stunnel already implements the client side, this would round out its LDAP support.

We have in fact already rebased the series onto 5.80 internally — I just didn't want to spam the list with an unsolicited resend unless there is interest. If the feature is of interest, I'd be glad to send the rebased version and do whatever else is needed to get it into a mergeable shape — adjusting the coding style to match the project's conventions, reworking or reducing the tests, resubmitting the series inline instead of as attachments, or adding documentation. Just let me know what you'd prefer.

Of course, if it's not something you'd want upstream, that's absolutely fine too — I'd appreciate a quick note either way.

Thank you very much for stunnel and for your work.

Best regards,
Steffen Heil

 



From: Steffen Heil | secforge
Sent: Wednesday, 13 May 2026 14:40:17
To: stunnel-users@lists.stunnel.org <stunnel-users@lists.stunnel.org>
Cc: Michal.Trojnara@stunnel.org <Michal.Trojnara@stunnel.org>
Subject: [PATCH 0/3] LDAP server-side STARTTLS support

 

Hi Michal,

 

This series adds server-side STARTTLS support for the LDAP protocol

handler (RFC 2830).  Three patches are attached:

 

  0001 — core feature (src/protocol.c only)

  0002 — automated test plugin for make check

  0003 — optional Docker-based live integration test [RFC]

 

Background

----------

stunnel already supports LDAP STARTTLS on the client side

(ldap_client_middle): it connects to an LDAP backend, sends a StartTLS

ExtendedRequest, waits for the success response, and then performs the

TLS handshake toward the backend.

 

The server side was missing.  Without it, stunnel could not act as a TLS

termination proxy in front of a plain LDAP backend for clients that

initiate connections using STARTTLS — a common deployment pattern where

legacy LDAP clients that do not support LDAPS (TLS-on-connect) still

expect to negotiate TLS via STARTTLS before sending credentials.

 

Patch 1 — core feature

-----------------------

Two new functions in src/protocol.c, mirroring the structure of the

existing client-side implementation:

 

  ldap_server_init

    Sets connect_before_ssl=1 so stunnel establishes the TCP connection

    to the backend before starting the TLS handshake with the local

    client.

 

  ldap_server_middle

    Reads the incoming LDAPMessage from the client and validates it as a

    StartTLS ExtendedRequest (APPLICATION 23, OID 1.3.6.1.4.1.1466.20037).

    Extracts the messageID and sends back a well-formed StartTLS

    ExtendedResponse (APPLICATION 24, resultCode=success) with the

    matching messageID.  stunnel then performs SSL_accept with the client.

    WinLDAP-style four-byte length encoding is handled, matching the

    existing client-side behaviour.

 

Both functions are registered in the PROTOCOL dispatch table under the

existing "ldap" name, so protocol = ldap now works for both client and

server services.

 

Patch 2 — automated tests

--------------------------

p28_ldap_starttls.py adds two tests to make check:

 

  Test 281: the Python test harness performs the RFC 2830 StartTLS

  exchange directly against a stunnel server (protocol=ldap), then

  upgrades to TLS via asyncio's loop.start_tls(), exercising

  ldap_server_middle in isolation.

 

  Test 282: a full client→server proxy chain where both stunnel

  instances run with protocol=ldap, exercising ldap_client_middle and

  ldap_server_middle together end-to-end.

 

Patch 3 — live integration test [RFC / optional]

-------------------------------------------------

ldap_starttls_live_test.sh is a shell script that runs against a real

OpenLDAP server (osixia/openldap) in Docker.  It requires Docker,

ldapsearch/ldapadd, and openssl, so it is not part of make check.

 

I'm sending it as an optional follow-up in case it is useful for

manual verification or as a starting point for a CI stage.  Feel free

to drop it if it does not fit the project's test infrastructure.

 

License

-------

I dedicate my contributions in this patch series to the public domain,

in line with the contribution policy stated in CREDITS.md.

 

Regards,

 

Steffen Heil

Geschäftsführer 

_______________________________________________________________________________

 

secforge GmbH 

Starterzentrum | Campus A1.1 | 66123 Saarbrücken | Deutschland

Phone: +49 179 2339260 | +49 681 93355440 

E-Mail: steffen.heil@secforge.de

Web: https://www.secforge.de

Registergericht:  Amtsgerichts Saarbrücken | HRB 109882 

Geschäftsführer: Steffen Heil, Dr. Mikhail Kovalev