Skip to content

PSMDB-1998 Add timeouts to LDAP connect/bind operations#1756

Merged
igorsol merged 7 commits intov8.0from
psmdb-1998-80
Mar 19, 2026
Merged

PSMDB-1998 Add timeouts to LDAP connect/bind operations#1756
igorsol merged 7 commits intov8.0from
psmdb-1998-80

Conversation

@igorsol
Copy link
Copy Markdown

@igorsol igorsol commented Mar 19, 2026

Apply ldapTimeoutMS to LDAP connection establishment and bind operations, not just search queries. Without these timeouts, auth requests hang indefinitely when the LDAP server is unreachable, causing connection pile-up and eventual file descriptor exhaustion.

Changes:

  • Set LDAP_OPT_NETWORK_TIMEOUT and LDAP_OPT_TIMEOUT on all LDAP handles (both pool and per-auth connections) using ldapTimeoutMS
  • Check LDAPbind() return value in borrow_search_connection() to avoid returning broken connections
  • Add timeout to connection pool condvar wait to prevent threads from blocking indefinitely when all pool slots are occupied
  • Fix LDAP handle leak in create_connection() error paths using ScopeGuard
  • Use local LDAP handle in OpenLDAPServerMechanism::stepImpl (Replace the _ld class member with a local variable and ScopeGuard to ensure the LDAP connection is released immediately after the single-step auth completes, rather than lingering until the mechanism object is destroyed.)
  • Bind LDAP pool connections once at creation time (do not bind on each search query)
  • Invalidate LDAP connection pool on parameter changes (ldapServers, ldapQueryUser, ldapQueryPassword parameters)

Add ldapauthz_ldap_timeouts.js test with two test scenarios:

  • Auth against a non-listening LDAP port fails gracefully and the server recovers when ldapServers is switched to a valid server
  • Auth fails with zero ldapTimeoutMS, proving LDAP_OPT_TIMEOUT is applied to bind operations
    Add ldapauthz_pool_invalidation.js to test that changing
    ldapQueryPassword at runtime invalidates pooled connections: auth
    fails with wrong credentials and succeeds again after restoring
    the correct password.

Convert _setup.js to an ES module exporting createAdminUser(conn) and remove dead load() calls from existing tests that never used the admin user created by the old setup.

Apply ldapTimeoutMS to LDAP connection establishment and bind
operations, not just search queries. Without these timeouts, auth
requests hang indefinitely when the LDAP server is unreachable,
causing connection pile-up and eventual file descriptor exhaustion.

Changes:
- Set LDAP_OPT_NETWORK_TIMEOUT and LDAP_OPT_TIMEOUT on all LDAP
  handles (both pool and per-auth connections) using ldapTimeoutMS
- Check LDAPbind() return value in borrow_search_connection() to
  avoid returning broken connections
- Add timeout to connection pool condvar wait to prevent threads
  from blocking indefinitely when all pool slots are occupied
- Fix LDAP handle leak in create_connection() error paths using
  ScopeGuard
@github-actions
Copy link
Copy Markdown

Backport Policy Overview

@igorsol, This branch (v8.0) is a production release branch and does not accept direct PRs.
All changes must flow through the corresponding staging branch (v8.0-staging), where they are tested and validated before being promoted into v8.0 by the Server Release team.

Next step: Please re-open this PR against v8.0-staging.

Please reach out in #server-release if you have any questions.

igorsol added 6 commits March 19, 2026 20:34
Add ldapauthz_ldap_timeouts.js with two test scenarios:
- Auth against a non-listening LDAP port fails gracefully and the
  server recovers when ldapServers is switched to a valid server
- Auth fails with zero ldapTimeoutMS, proving LDAP_OPT_TIMEOUT is
  applied to bind operations

Convert _setup.js to an ES module exporting createAdminUser(conn)
and remove dead load() calls from existing tests that never used the
admin user created by the old setup.
Replace the _ld class member with a local variable and ScopeGuard to
ensure the LDAP connection is released immediately after the single-step
auth completes, rather than lingering until the mechanism object is
destroyed.
Move LDAPbind() from borrow_search_connection() into borrow_or_create()
so pool connections are bound once when created rather than on every
borrow. This eliminates a round-trip to the LDAP server on each auth
or role query.

Add a destroy parameter to return_ldap_connection() so callers can
signal that a connection should be removed from the pool rather than
recycled. Use this in execQuery() retry and error paths to discard
connections after search failures.
Add a destroy flag to LDAPConnInfo so connections can be marked for
destruction when returned to the pool. Add invalidate_connections()
to ConnectionPoller which destroys idle connections immediately and
marks borrowed ones for destruction on return.

Expose invalidateConnections() through the LDAPManager interface.
Convert ldapQueryUser and ldapQueryPassword IDL parameters to use
custom cpp_class implementations that call invalidateConnections()
when values change at runtime. Also invalidate connections when
ldapServers changes, since existing connections point to the old
server.
Extend ldapauthz_ldap_timeouts.js Test 1 to verify that switching
ldapServers back to a non-listening port invalidates the pool and
causes auth to fail again.

Add ldapauthz_pool_invalidation.js to test that changing
ldapQueryPassword at runtime invalidates pooled connections: auth
fails with wrong credentials and succeeds again after restoring
the correct password.
@igorsol igorsol merged commit c1be7f5 into v8.0 Mar 19, 2026
5 checks passed
@igorsol igorsol deleted the psmdb-1998-80 branch March 19, 2026 21:14
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.

1 participant