2

I want to get the details of digital certificate of a domain, if the digital certificate exists.

I want to build something like the Google Chrome security indicator.

To get the details of the digital certificate, I use this code:

    $cacert = $this->getParameter('kernel.root_dir') . '/../src/AppBundle/Resources/public/security/cacert.pem';

    $host = 'www.mywebsite.it';

    $contextOptions = [
        'http' => [
            'ignore_errors' => true
        ],
        'ssl' => [
            'verify_peer' => false,
            'cafile' => $cacert,
            //'peer_name' => $host,
            'ciphers' => 'HIGH',
            'disable_compression' => true,
            'capture_peer_cert' => true,
            'capture_peer_cert_chain' => true
        ],
    ];

    $context = stream_context_create($contextOptions);

    $domain = preg_replace('/(http:\/\/)|(https:\/\/)/', '', $host);
    $socket = stream_socket_client(
        'ssl://' . $domain . ':443',
        $errno,
        $errstr,
        30,
        STREAM_CLIENT_CONNECT,
        $context
        );

    if (!$socket) {
        echo "$errstr ($errno)<br />\n";
    }

    $params = stream_context_get_params($socket);

    $cert_resource = $params['options']['ssl']['peer_certificate'];
    $cert = openssl_x509_parse($cert_resource);

    dump($cert);die;

This code was taken from here.

What I'd like to achieve is a script that can behave like the Google Chrome SSL certificate Checker, so I'd like to know if a website is secure or not and, if yes, how much it is. Details about Google Chrome security indicators can be found here.

THE PROBLEMS/QUESTIONS

1) stream_socket_client() raises some Warnings if problems happen instead of using \Exceptions. So, how can I intercept Warnings to understand what is happening? Is the custom error handler the only solution as suggested here, here, here and here?

As you can see from the code above, I've also set the http ignore_errors property to false, but this seems not working (see point number 2, the following). This possible solution was suggested here.

2) My domain hasn't a digital certificate, but my server has one, so, when I try to get the certificate, I get the following error:

Warning: stream_socket_client(): Peer certificate CN='ssl.my.server.com' did not match expected CN='www.mydomain.it'

So, I cannot get the certificate details because the connection stops before I get them. How can I get anyway the details of the certificate? Is this connection secure or not? Is the difference with a green Chrome bar only the fact that the certificate is for a domain different than the one called? But this connection is secure or not?

3) I've tried to get the certificate details of a domain without a certificate (also the server hasn't one) and I get this warning:

Warning: stream_socket_client(): unable to connect to ssl://www.non-secure-domain.com:443 (Operation timed out)

Is this error sufficient to say the domain hasn't a digital certificate at all? Which is the difference between this error and the one I get at the point 2?

4) The last question: as it is possible to connect to a remote host also via cURL, should have I to use cURL or it sufficient stream_socket_client()? Which is the difference between the two for my use case (getting the digital certificate details)?

Thank you for your advices :)

Community
  • 1
  • 1
Aerendir
  • 6,152
  • 9
  • 55
  • 108

0 Answers0