Start · Sprachen · PHP · Referenz · ldap_start_tls

ldap_start_tls

Funktion

Startet eine TLS-Verbindung auf einem bereits geöffneten LDAP-Handle, um die Kommunikation zu verschlüsseln.

seit PHP 4.2.0 Kategorie: misc

Signatur

ldap_start_tls(LDAP\Connection $ldap): bool

Beschreibung

ldap_start_tls() initiiert das STARTTLS-Protokoll auf einer bestehenden, unverschlüsselten LDAP-Verbindung. Dabei wird innerhalb der bestehenden TCP-Verbindung auf Port 389 ein TLS-Handshake durchgeführt, ohne eine neue Verbindung aufzubauen. Dies unterscheidet STARTTLS vom klassischen LDAPS (Port 636), bei dem TLS von Anfang an besteht.

Die Funktion sollte unmittelbar nach ldap_connect() und vor ldap_bind() aufgerufen werden, damit Zugangsdaten und alle weiteren LDAP-Operationen verschlüsselt übertragen werden. Eine unverschlüsselte Übertragung von Bind-Credentials ist ein erhebliches Sicherheitsrisiko.

Damit die Funktion funktioniert, muss die OpenLDAP-Bibliothek korrekt konfiguriert sein (z. B. TLS_REQCERT in /etc/ldap/ldap.conf) und das Zertifikat des LDAP-Servers muss vertrauenswürdig sein. Mit ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER) kann die Zertifikatsprüfung deaktiviert werden, was jedoch nur in Testumgebungen akzeptabel ist.

Schlägt der TLS-Handshake fehl, gibt die Funktion false zurück und löst eine PHP-Warnung aus. Mit ldap_errno() und ldap_error() lassen sich detaillierte LDAP-Fehlercodes auslesen.

Parameter

Name Typ Default Beschreibung
$ldap Pflicht LDAP\Connection Eine gültige LDAP-Verbindungsressource, wie sie von ldap_connect() zurückgegeben wird. Ab PHP 8.1 ist dies ein LDAP\Connection-Objekt.

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn der TLS-Handshake erfolgreich war. Bei einem Fehler (z. B. ungültiges Zertifikat, nicht unterstütztes Protokoll) wird false zurückgegeben und eine PHP-Warnung erzeugt.

Beispiele

Sichere LDAP-Verbindung mit STARTTLS und anschließendem Bind

<?php
$host = 'ldap://ldap.example.com';
$dn   = 'cn=admin,dc=example,dc=com';
$pass = 'geheimes_passwort';

$ldap = ldap_connect($host);
if (!$ldap) {
    die('Verbindung fehlgeschlagen.');
}

// Optionen vor STARTTLS setzen
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

// TLS starten
if (!ldap_start_tls($ldap)) {
    die('STARTTLS fehlgeschlagen: ' . ldap_error($ldap));
}

// Jetzt verschlüsselt binden
if (!ldap_bind($ldap, $dn, $pass)) {
    die('Bind fehlgeschlagen: ' . ldap_error($ldap));
}

echo 'Erfolgreich verschlüsselt verbunden und authentifiziert.';

ldap_unbind($ldap);
Erfolgreich verschlüsselt verbunden und authentifiziert.

STARTTLS mit deaktivierter Zertifikatsprüfung (nur für Tests)

<?php
// ACHTUNG: Nur in Entwicklungs-/Testumgebungen verwenden!
// Deaktiviert die Zertifikatsvalidierung global (vor ldap_connect)
ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);

$ldap = ldap_connect('ldap://ldap-test.local');
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

if (ldap_start_tls($ldap)) {
    echo 'TLS gestartet (ohne Zertifikatsprüfung).';
    ldap_bind($ldap, 'cn=testuser,dc=local', 'test123');
    // ... Operationen ...
    ldap_unbind($ldap);
} else {
    echo 'TLS-Start fehlgeschlagen.';
}
TLS gestartet (ohne Zertifikatsprüfung).

// Wichtig · Fallstricke

Sicherheitshinweis: Verwende ldap_start_tls() niemals ohne anschließende Validierung des Server-Zertifikats in Produktionsumgebungen. Das Deaktivieren der Zertifikatsprüfung (LDAP_OPT_X_TLS_NEVER) macht die Verbindung anfällig für Man-in-the-Middle-Angriffe.

Reihenfolge beachten: ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3) muss vor ldap_start_tls() gesetzt werden, da STARTTLS nur mit LDAP v3 funktioniert.

STARTTLS vs. LDAPS: STARTTLS (Port 389) und LDAPS (Port 636, via ldaps://-URI) sind zwei verschiedene Wege zur Verschlüsselung. Beide sind in modernen Umgebungen akzeptabel; LDAPS gilt bei manchen als etwas robuster, da TLS von Beginn an aktiv ist.

PHP 8.1: Ab PHP 8.1 wurde die Ressource durch das LDAP\Connection-Objekt ersetzt. Code, der noch eine alte Ressource erwartet, muss entsprechend angepasst werden.