php / php/php-src

LDAPS client certificate authentication does not work

Abierto
#12,081 6 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Bug Extension: ldap Status: Needs Triage
Lenguaje dominante
C
Estrellas
40.4k
Forks
8.1k
Merge medio
2 d 13 h
PR fusionados (30 d)
96

Descripción

Description

The following code:

<?php

// Test case for PHP bug: https://bugs.php.net/bug.php?id=73558
//
// The two commands below work totally fine:
//
// OpenSSL:
// $ openssl s_client -verifyCAfile ca.crt -cert ldap-client.crt -key ldap-client.key -connect ldap.home.arpa:636
//
// ldapsearch:
// $ LDAPTLS_CACERT=ca.crt LDAPTLS_CERT=ldap-client.crt LDAPTLS_KEY=ldap-client.key ldapwhoami -H ldaps://ldap.home.arpa -x
// anonymous

$ldapUri = 'ldaps://ldap.home.arpa';
$caFile = __DIR__.'/ca.crt';
$certFile = __DIR__.'/ldap-client.crt';
$keyFile = __DIR__.'/ldap-client.key';

//putenv(sprintf('LDAPTLS_CACERT=%s', $caFile));
//putenv(sprintf('LDAPTLS_CERT=%s', $certFile));
//putenv(sprintf('LDAPTLS_KEY=%s', $keyFile));

$ldapResource = ldap_connect($ldapUri);
$ldapOptions = [
    LDAP_OPT_PROTOCOL_VERSION => 3,
    LDAP_OPT_REFERRALS => 0,
    LDAP_OPT_X_TLS_CACERTFILE => $caFile,
    LDAP_OPT_X_TLS_CERTFILE => $certFile,
    LDAP_OPT_X_TLS_KEYFILE => $keyFile,
];

foreach($ldapOptions as $k => $v) {
    ldap_set_option($ldapResource, $k, $v);
}

if(false === ldap_bind($ldapResource)) {
    ldap_get_option($ldapResource, LDAP_OPT_DIAGNOSTIC_MESSAGE, $errMsg);
    echo sprintf(
        "%s (%d): %s\n",
        ldap_error($ldapResource),
        ldap_errno($ldapResource),
        $errMsg
    );
}

var_dump(
    ldap_exop_whoami($ldapResource)
);

Resulted in this output:

PHP Warning:  ldap_bind(): Unable to bind to server: Can't contact LDAP server in /home/fkooman/ldap.home.arpa/ldap_test.php on line 36
Can't contact LDAP server (-1): error:0A000086:SSL routines::certificate verify failed (self-signed certificate in certificate chain)
PHP Warning:  ldap_exop_whoami(): Whoami extended operation failed: Can't contact LDAP server (-1) in /home/fkooman/ldap.home.arpa/ldap_test.php on line 47
bool(false)

But I expected this output instead (anonymous bind):

string(0) ""

Workaround

When you enable the three putenv lines, things start working, but this probably not how it should be :)

Additional details

It seems the options LDAP_OPT_X_TLS_CACERTFILE, LDAP_OPT_X_TLS_CERTFILE and LDAP_OPT_X_TLS_KEYFILE are somehow ignored.

We tested this on Fedora 38 (PHP 8.2.9 (cli) (built: Aug 3 2023 11:39:08) (NTS gcc x86_64)):

LDAP Support => enabled
Total Links => 0/unlimited
API Version => 3001
Vendor Name => OpenLDAP
Vendor Version => 20604
SASL Support => Enabled

Directive => Local Value => Master Value
ldap.max_links => Unlimited => Unlimited

And on Debian 12 (PHP 8.2.7 (cli) (built: Jun 9 2023 19:37:27) (NTS)):

LDAP Support => enabled
Total Links => 0/unlimited
API Version => 3001
Vendor Name => OpenLDAP
Vendor Version => 20513
SASL Support => Enabled

Directive => Local Value => Master Value
ldap.max_links => Unlimited => Unlimited

See also: https://bugs.php.net/bug.php?id=73558

Test Setup without LDAP server

If you do not have an LDAP server, you can also use openssl to create a test server that results in the exact same error message in the PHP script as the problem is in the TLS setup, not the actual LDAP connection:

$ openssl s_server -CAfile ca.crt -cert ldap.home.arpa.crt -key ldap.home.arpa.key

All you need is the client cert/key, server cert/key and CA and connect to port 4433 (the default of s_server).

PHP Version

PHP 8.2.9 / 8.2.7

Operating System

Fedora 38 / Debian 12

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con el script de PHP proporcionado, especialmente con ldap_set_option(), ldap_bind() y las opciones LDAP_OPT_X_TLS_*, y luego reproduce la configuración de TLS con el comando openssl s_server mostrado. Compara este procedimiento con la configuración mediante variables de entorno que funciona. Se considera terminado cuando se respetan las opciones de certificado y tanto el bind como ldap_exop_whoami() tienen éxito sin el error de verificación del certificado.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
php
Área
authentication, networking, security
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.