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

> Discover how Doom supports both LDAP and LDAPS connections. Our guide explains the dual-protocol authentication process and fallback mechanism for secure access.

- Repository: [000pp/doom](https://github.com/000pp/doom)
- Tags: how-to-guide
- Published: 2026-02-22

---

**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`](https://github.com/000pp/doom/blob/main/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:

```python
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`](https://github.com/000pp/doom/blob/main/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:

```python
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`](https://github.com/000pp/doom/blob/main/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`](https://github.com/000pp/doom/blob/main/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`.