Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, $option) can't be overridden #17776

Open
robert-scheck opened this issue Feb 12, 2025 · 1 comment

Comments

@robert-scheck
Copy link

Description

The following code:

<?php
  ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 6);

  echo 'Test LDAP_OPT_X_TLS_ALLOW' . PHP_EOL;
  if (!ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_ALLOW)) {
    echo 'Unable to set LDAP_OPT_X_TLS_ALLOW!' . PHP_EOL;
  }
  $ldapconn1 = ldap_connect('ldaps://localhost:636');
  ldap_set_option($ldapconn1, LDAP_OPT_PROTOCOL_VERSION, 3);
  $ldapbind1 = ldap_bind($ldapconn1, 'CN=Administrator,CN=Users,DC=samdom,DC=example,DC=com', 'Passw0rd');
  if ($ldapbind1) {
    echo 'LDAP bind succeeded (expected)' . PHP_EOL;
  } else {
    echo 'LDAP bind failed (unexpected)' . PHP_EOL;
  }
  ldap_unbind($ldapconn1);

  echo PHP_EOL;

  echo 'Test LDAP_OPT_X_TLS_DEMAND' . PHP_EOL;
  if (!ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_DEMAND)) {
    echo 'Unable to set LDAP_OPT_X_TLS_DEMAND!' . PHP_EOL;
  }
  $ldapconn2 = ldap_connect('ldaps://localhost:636');
  ldap_set_option($ldapconn2, LDAP_OPT_PROTOCOL_VERSION, 3);
  $ldapbind2 = ldap_bind($ldapconn2, 'CN=Administrator,CN=Users,DC=samdom,DC=example,DC=com', 'Passw0rd');
  if ($ldapbind2) {
    echo 'LDAP bind succeeded (unexpected)' . PHP_EOL;
  } else {
    echo 'LDAP bind failed (expected)' . PHP_EOL;
  }
  ldap_unbind($ldapconn2);
EOF

Resulted in this output:

Test LDAP_OPT_X_TLS_ALLOW
TLS certificate verification: Error, unable to get local issuer certificate
TLS certificate verification: Error, unable to verify the first certificate
LDAP bind succeeded (expected)

Test LDAP_OPT_X_TLS_DEMAND
TLS certificate verification: Error, unable to get local issuer certificate
TLS certificate verification: Error, unable to verify the first certificate
TLS: unable to get peer certificate.
LDAP bind succeeded (unexpected)

But I expected this output instead:

Test LDAP_OPT_X_TLS_ALLOW
TLS certificate verification: Error, unable to get local issuer certificate
TLS certificate verification: Error, unable to verify the first certificate
LDAP bind succeeded (expected)

Test LDAP_OPT_X_TLS_DEMAND
TLS certificate verification: Error, unable to get local issuer certificate
TLS: can't connect: error:0A000086:SSL routines::certificate verify failed (unable to get local issuer certificate).
PHP Warning:  ldap_bind(): Unable to bind to server: Can't contact LDAP server in /tmp/ldap.php on line 26
LDAP bind failed (expected)

Full reproducer:

  1. docker run --rm -it docker.io/smblds/smblds:latest /bin/sh
  2. rm -f /root/.ldaprc
  3. apk update
  4. apk add php84-cli php84-ldap
cat > /tmp/ldap.php <<\EOF
<?php
  ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 6);

  echo 'Test LDAP_OPT_X_TLS_ALLOW' . PHP_EOL;
  if (!ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_ALLOW)) {
    echo 'Unable to set LDAP_OPT_X_TLS_ALLOW!' . PHP_EOL;
  }
  $ldapconn1 = ldap_connect('ldaps://localhost:636');
  ldap_set_option($ldapconn1, LDAP_OPT_PROTOCOL_VERSION, 3);
  $ldapbind1 = ldap_bind($ldapconn1, 'CN=Administrator,CN=Users,DC=samdom,DC=example,DC=com', 'Passw0rd');
  if ($ldapbind1) {
    echo 'LDAP bind succeeded (expected)' . PHP_EOL;
  } else {
    echo 'LDAP bind failed (unexpected)' . PHP_EOL;
  }
  ldap_unbind($ldapconn1);

  echo PHP_EOL;

  echo 'Test LDAP_OPT_X_TLS_DEMAND' . PHP_EOL;
  if (!ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_DEMAND)) {
    echo 'Unable to set LDAP_OPT_X_TLS_DEMAND!' . PHP_EOL;
  }
  $ldapconn2 = ldap_connect('ldaps://localhost:636');
  ldap_set_option($ldapconn2, LDAP_OPT_PROTOCOL_VERSION, 3);
  $ldapbind2 = ldap_bind($ldapconn2, 'CN=Administrator,CN=Users,DC=samdom,DC=example,DC=com', 'Passw0rd');
  if ($ldapbind2) {
    echo 'LDAP bind succeeded (unexpected)' . PHP_EOL;
  } else {
    echo 'LDAP bind failed (expected)' . PHP_EOL;
  }
  ldap_unbind($ldapconn2);
EOF
  1. php84 /tmp/ldap.php
  2. If I reverse the two tests, both tests will fail for LDAP bind instead of both succeeding

If I'm not overlooking something, ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, $option) can't be overridden, but I also don't receive any failure for ldap_set_option(). And $ldapconn = ldap_connect('ldaps://localhost:636'); ldap_set_option($ldapconn, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_ALLOW); doesn't work.

PHP Version

PHP 8.4.3 (with OpenLDAP 2.6.8)

Operating System

Alpine Linux 3.21.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants