Are you willing to create (at a later stage) a PR for that?
Yes
iTop version
2.7.3(3.23)
PHP version
7.4.33
Reproduction procedure
Problem
When using Google Secure LDAP (ldaps://ldap.google.com:636) with client certificates,
the first authentication attempt always fails with:
"Can't contact LDAP server"
Subsequent attempts succeed. This happens because each new PHP-FPM worker process
fails on the first bind.
Root Cause
In model.authent-ldap.php, TLS options (LDAP_OPT_X_TLS_CACERTFILE,
LDAP_OPT_X_TLS_CERTFILE, LDAP_OPT_X_TLS_KEYFILE) are set via
ldap_set_option($hDS, ...) after ldap_connect().
However, OpenLDAP requires these options to be set globally via
ldap_set_option(null, ...) before ldap_connect() so that the TLS
context is initialized correctly during the connection handshake.
Current code order (broken for Google LDAP):
ldap_connect() ← TLS handshake happens here, no cert yet
foreach $aOptions ← TLS options set too late
ldap_bind() ← fails on first attempt
Fix: set TLS options before ldap_connect():
foreach $aOptions with ldap_set_option(null, ...) ← global context
ldap_set_option(null, LDAP_OPT_X_TLS_NEWCTX, 0) ← reinit TLS context
ldap_connect()
ldap_bind() ← works reliably
Environment
- iTop: 2.7.3 (reproduced, same code in 3.2.3)
- LDAP server: Google Workspace Secure LDAP (ldap.google.com:636, ldaps://)
- PHP: 7.4.33
- OpenSSL: 3.0.13
- OS: Ubuntu, nginx + PHP-FPM
References
Additional information (if needed)
PR: #945
Are you willing to create (at a later stage) a PR for that?
Yes
iTop version
2.7.3(3.23)
PHP version
7.4.33
Reproduction procedure
Problem
When using Google Secure LDAP (ldaps://ldap.google.com:636) with client certificates,
the first authentication attempt always fails with:
"Can't contact LDAP server"
Subsequent attempts succeed. This happens because each new PHP-FPM worker process
fails on the first bind.
Root Cause
In
model.authent-ldap.php, TLS options (LDAP_OPT_X_TLS_CACERTFILE,LDAP_OPT_X_TLS_CERTFILE, LDAP_OPT_X_TLS_KEYFILE) are set via
ldap_set_option($hDS, ...)afterldap_connect().However, OpenLDAP requires these options to be set globally via
ldap_set_option(null, ...)beforeldap_connect()so that the TLScontext is initialized correctly during the connection handshake.
Current code order (broken for Google LDAP):
ldap_connect()← TLS handshake happens here, no cert yetforeach $aOptions← TLS options set too lateldap_bind()← fails on first attemptFix: set TLS options before ldap_connect():
foreach $aOptionswithldap_set_option(null, ...)← global contextldap_set_option(null, LDAP_OPT_X_TLS_NEWCTX, 0)← reinit TLS contextldap_connect()ldap_bind()← works reliablyEnvironment
References
https://support.google.com/a/answer/9089736
https://www.php.net/manual/en/function.ldap-set-option.php
Additional information (if needed)
PR: #945