Can Doom Connect Using Both LDAP and LDAPS? A Complete Guide to Dual-Protocol Authentication

Yes, Doom automatically supports both LDAP and LDAPS connections through a single helper function that attempts unsecured LDAP first and transparently falls back to LDAPS when stronger authentication is required.

The 000pp/doom repository provides a robust LDAP authentication module that eliminates manual protocol selection. Whether your Active Directory environment requires standard LDAP on port 389 or encrypted LDAPS on port 636, Doom handles the negotiation automatically without requiring separate configuration flags.

How Doom Implements Dual-Protocol LDAP Support

The core logic resides in src/doom/protocols/ldap.py, specifically within the get_ldap_connection function. This implementation uses the ldap3 library to create a seamless authentication experience that adapts to server requirements in real-time.

The Connection Logic: LDAP First, LDAPS Fallback

When initiating a connection, Doom follows a specific priority sequence:

  1. Initial LDAP attempt: The function first creates a server object targeting ldap://{host} on port 389 with use_ssl=False.
  2. NTLM authentication: It attempts to bind using NTLM authentication with session_security="ENCRYPT" requested.
  3. Fallback trigger: If the server responds with a strongerAuthRequired error, the code catches this specific exception and proceeds to LDAPS.

This approach ensures compatibility with environments that support both protocols while prioritizing the less restrictive connection when possible.

TLS Configuration and Certificate Handling

For the LDAPS fallback, Doom configures a TLS context that disables certificate validation—a common requirement for internal Active Directory environments using self-signed certificates:

tls = ldap3.Tls(
    validate=ssl.CERT_NONE,
    version=ssl.PROTOCOL_TLSv1_2,
    ciphers='ALL:@SECLEVEL=0'
)

The LDAPS server object targets ldaps://{host} on port 636 with use_ssl=True and the custom TLS context applied.

Authenticating with NTLM and Pre-Hashed Credentials

The get_ldap_connection function handles credential formatting automatically:

  • Domain user construction: It builds the NTLM user string as f"{domain}\\{username}" (line 10 in src/doom/protocols/ldap.py).
  • Pre-hashed password detection: If the provided password is exactly 32 characters, the function assumes an NTLM hash and prepends the aad3b435b51404eeaad3b435b51404ee prefix (lines 12-14).

This allows penetration testers to pass either cleartext passwords or pre-computed NTLM hashes without modifying the connection logic.

Practical Implementation: Using get_ldap_connection

Here is a complete example demonstrating how to use Doom's LDAP functionality in your own scripts:

from doom.protocols.ldap import get_ldap_connection

# Define connection parameters

host = "ad.example.com"
username = "jdoe"
password = "Password123!"  # Or 32-char NTLM hash

domain = "EXAMPLE"

try:
    # Attempt connection (LDAP first, LDAPS fallback)

    conn, base_dn = get_ldap_connection(host, username, password, domain)
    
    # Determine which protocol succeeded

    protocol = "LDAPS" if conn.server.use_ssl else "LDAP"
    print(f"Successfully connected via {protocol}")
    print(f"Base DN: {base_dn}")
    
    # Perform LDAP queries

    conn.search(
        search_base=base_dn,
        search_filter="(objectClass=user)",
        attributes=["sAMAccountName", "mail"]
    )
    
    for entry in conn.entries:
        print(f"User: {entry.sAMAccountName}, Email: {entry.mail}")
        
except Exception as e:
    print(f"Connection failed: {e}")
finally:
    if 'conn' in locals():
        conn.unbind()

This implementation automatically handles the protocol negotiation, allowing you to focus on querying Active Directory rather than managing connection parameters.

Summary

  • Doom's get_ldap_connection function in src/doom/protocols/ldap.py provides automatic dual-protocol support.
  • The implementation attempts LDAP on port 389 first, then falls back to LDAPS on port 636 if the server requires stronger authentication.
  • NTLM authentication is used for both protocols, with support for both cleartext passwords and pre-hashed NTLM tokens.
  • The TLS context disables certificate validation by default, accommodating internal AD environments with self-signed certificates.
  • No manual protocol selection is required; the function handles negotiation transparently.

Frequently Asked Questions

Does Doom require separate configuration for LDAP and LDAPS?

No. The get_ldap_connection function handles both protocols automatically. You only need to provide the hostname, username, password, and domain. The code first attempts a standard LDAP connection on port 389, and only if the server responds with a strongerAuthRequired error does it switch to LDAPS on port 636.

What authentication method does Doom use for LDAP connections?

Doom uses NTLM authentication for both LDAP and LDAPS connections. The implementation constructs the user string in the format domain\username and supports both cleartext passwords and pre-computed NTLM hashes. When using hashes, the code automatically prepends the required aad3b435b51404eeaad3b435b51404ee prefix to the 32-character hash.

Is certificate validation enabled for LDAPS connections?

No, certificate validation is disabled by default. The TLS context in src/doom/protocols/ldap.py explicitly sets validate=ssl.CERT_NONE and uses ciphers='ALL:@SECLEVEL=0'. This configuration is designed to work with internal Active Directory environments that commonly use self-signed or enterprise certificates that might not validate against standard trust stores.

Which port numbers does Doom use for LDAP and LDAPS?

Doom uses the standard port numbers: port 389 for unsecured LDAP and port 636 for LDAPS. These are hardcoded in the server object definitions within the get_ldap_connection function. The LDAP server object targets ldap://{host} with use_ssl=False, while the LDAPS server object targets ldaps://{host} with use_ssl=True.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →