How to save the LDAP SSL Certificate from OpenSSL

The easiest way i found to save a certificate from any SSL enabled protocols like ldap, imap, pop, ftps, https etc. is just using chrome browser. Assume if your server running any protocol (like mentioned) create the url like this

http://: (example if your ldap server is running on SSL port 10636 it would be https://example.com:10636). Simply just hit this URL and obtain the certificate from the chrome browser itself. A simple demo below. In this demo my ldap server is using a self-signed certificate.

Click On Certificate Information

Click on copy to file and save the certificate by clicking next.

enter image description here

This method works for any server running on SSL irrespective of protocol.

Cheers.


There is a tool that lets you collect and save an SSL/TLS certificate from a server that speaks not only LDAPS, but LDAP/STARTTLS too. That's a revision of the well-known InstallCert program, written in Java.

Just run it like this:

java -jar installcert-usn-20131123.jar host_name:port

and it will save the certificate for you in the jssecacerts keystore file in your JRE file tree, and also in the extracerts keystore file in your current directory. You can then use Java keytool to export the certificate(s) to other formats.

You are welcome to visit my blog page Yet another InstallCert for Java, now with STARTTLS support for download and instructions.


Copy everything between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- (including these delimiters) and paste it in a new text file (usually with the extension .pem or .crt). You can use your favourite (plain) text editor for this, for example Notepad, Gedit, Vim, Emacs (depending on the system you're using).

Alternatively, you can pipe the output to sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p', as described here:

echo -n | openssl s_client -connect 192.168.1.225:636 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ldapserver.pem

For those looking to grab the certs over a LDAP connection using StartTLS:

I have re-submitted a patch to OpenSSL to support LDAP when using -starttls for s_client. So eventually this should work (if it ever makes it in I guess -- not yet as of 10/18/16):

openssl s_client -connect servername:389 -starttls ldap -showcerts

Edit: Support was eventually merged under this PR. C is not my forte so luckily someone else ran with it ;)

I also wrote a PHP function to extract the SSL certificates after issuing a STARTTLS command over a TCP connection. It could easily be ported to other languages with a little work:

/**
 * @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;
}

The above function will return an array containing the peer certificate and the peer certificate chain. So it could be used like so:

// 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;
}