Для тех, кто хочет получить сертификаты через соединение LDAP с помощью StartTLS:
Я повторно отправил патч в OpenSSL для поддержки LDAP при использовании -starttls для s_client. Таким образом, в конечном итоге это должно сработать (если это когда-нибудь произойдет, я думаю - еще не по состоянию на 18.10.16) :
openssl s_client -connect servername:389 -starttls ldap -showcerts
Редактировать : Поддержка была в конечном итоге объединена в этот PR . C не моя сильная сторона, так что, к счастью, кто-то еще бежал с ней;)
Я также написал функцию PHP для извлечения SSL-сертификатов после выполнения команды STARTTLS по TCP-соединению. Его можно легко перенести на другие языки с небольшой работой:
/**
* @param string $server The server name to connect to
* @param int $port The standard LDAP port
* @return array In the form of ['peer_certificate' => '', 'peer_certificate_chain' => [] ]
*/
function getLdapSslCertificates($server, $port = 389)
{
$certificates = [
'peer_certificate' => null,
'peer_certificate_chain' => [],
];
// This is the hex encoded extendedRequest for the STARTTLS operation...
$startTls = hex2bin("301d02010177188016312e332e362e312e342e312e313436362e3230303337");
$opts = [
'ssl' => [
'capture_peer_cert' => true,
'capture_peer_cert_chain' => true,
'allow_self_signed' => true,
'verify_peer' => false,
'verify_peer_name' => false,
],
];
$context = stream_context_create($opts);
$client = @stream_socket_client(
"tcp://$server:$port",
$errorNumber,
$errorMessage,
5,
STREAM_CLIENT_CONNECT,
$context
);
@stream_set_timeout($client, 2);
@fwrite($client, $startTls);
@fread($client, 10240);
@stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
$info = @stream_context_get_params($client);
if (!$info) {
return $certificates;
}
openssl_x509_export($info['options']['ssl']['peer_certificate'], $certificates['peer_certificate']);
foreach ($info['options']['ssl']['peer_certificate_chain'] as $index => $cert) {
$certChain = '';
openssl_x509_export($cert, $certChain);
$certificates['peer_certificate_chain'][$index] = $certChain;
}
@fclose($client);
return $certificates;
}
Приведенная выше функция вернет массив, содержащий сертификат однорангового узла и цепочку сертификатов однорангового узла. Так что это можно использовать так:
// Just pass it the server name
$certificates = getLdapSslCertificates('dc1.example.local');
// The certificates are in the array as strings in PEM format
echo $certificates['peer_certificate'].PHP_EOL;
foreach ($certificates['peer_certificate_chain'] as $cert) {
echo $cert.PHP_EOL;
}