PHP for checking SSL Certificate Authority

Hi, I’m not clear on the technical issues involved, but does anyone know if it is possible to read information about a website’s SSL certificate via PHP (with or without cURL?)

Basically, when I get to a secure website via http, regardless of whether I make a successful secure connection, I can view information from that website in my browser about the issuing authority, when the certificate expires, etc, etc (on IE, its by double clicking on the lock in the corner).

Does anyone know if it is possible to get this information via PHP? Basically I want to create a script that can automatically check a website and tell me what SSL cert it currently uses (if any), who is the issuing authority (Verisign, Comodo, etc) and when that cert expires.

I’m not looking to actually make a secure connection, but to “check” information about the host server in question. I’ve checked the headers, and did not see anything there.

Thanks,
~ Nexus

To start with, I would create a php script that does a

print_r($GLOBALS);

and

phpinfo();

and navigate to it while in SSL mode. PHP Server variables store quite a bit of useful information about the SSL capability of the website.

One other thing I would try, if your php script navigates to a website, dump out the HTTP headers. All the information that IE sees and uses when you click on the lock will be contained in them.

Thanks, escape. GTMA. Those were some of the first things I tried. To clarify, I’m trying to pull remote data. For instance, here’s what I can gather from Yahoo.com’s secure login site right now.

Querying them at ( login.yahoo.com ), I get the following chunk of data:

HTTP/1.0 200 OK
Date: Thu, 30 Oct 2003 16:58:42 GMT
P3P: policyref=“http://p3p.yahoo.com/w3c/p3p.xml”, CP=“CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV”
Cache-Control: private
Pragma: no-cache
Expires: Thu, 05 Jan 1995 22:00:00 GMT
Connection: close
Content-Type: text/html
Set-Cookie: B=as6kh4ovq2gq2&b=2; expires=Thu, 15 Apr 2010 20:00:00 GMT; path=/; domain=.yahoo.com

I also queried them through cURL from my server at https://login.yahoo.com and got the same result. The most interesting thing in there being their compact privacy policy.

Via the browser, I can read the following attributes from https://login.yahoo.com/ :

[b]Version:[/b] V1
[b]Serial number:[/b] #### DATA ####
[b]Signature algorithm:[/b] md2RSA
[b]Issuer:[/b] OU = Secure Server Certification Authority
         O = RSA Data Security, Inc.
         C = US
[b]Valid from:[/b] Tuesday, November 08, 1994 7:00:00 PM
[b]Valid to:[/b] Thursday, January 07, 2010 6:59:59 PM
[b]Subject:[/b] OU = Secure Server Certification Authority
          O = RSA Data Security, Inc.
          C = US
[b]Public Key:[/b] #### DATA ####
[b]Thumbprint algorithm:[/b] sha1
[b]Thumbprint:[/b] #### DATA ####
[b]Friendly name:[/b] VeriSign/RSA Secure Server CA
[b]Enhanced key usage (property):[/b] Server Authentication

Internet Explorer further lets me export this data in the following formats:

[list][]DER encoded binary X.509 (.CER)
[
]Base-64 encoded X-509 (.CER)
[*]Cryptographic Message Syntax Standard - PKC5 #7 Certificates (.P7B)[/list]

If I can get the certificate data remotely via PHP, that would be great. If it is somehow encoded, interfaced via some alternate protocol, or something, that’s what I’m trying to figure out and work around. I’d like to be able to query any site I want and have all this information able to be saved. The system I’m working on would correlate the data with other types of information a user would be managing. I’m trying to eliminate the “human error” aspect from someone entering this data into the system manually. Basic IT purposes.

Thanks,
~ DNexus

Ok, it seems like cURL in “verbose” mode pulls the information. If anyone knows of a non-cUrl technique for getting this, it’d be great. Thanks.

~ DNexus

I am pretty sure you could open a socket and get it that way. Just send the “GET / HTTP/1.1” string to https://login.yahoo.com and you should get back the entire request, headers and all. It might be harder to parse these out though.

Just a thought.

escape, I’m beginning to feel that no information regarding the presence of a certificate is passed unless you are coming through the HTTPS scheme, and that because the HTTPS scheme cannot be accessed via a simple TCP socket connection, if you cannot specify this, you have a non-starter.

Using the “fsockopen” function, gets me in, but I then need to use “ssl://” in front of my URL (and not “https://”). Notes from the PHP site state that this method is not supported on Windows machines until possibly version 4.5 CVS unless you obtain a special DLL, and not supported otherwise if PHP is not compiled with OpenSSL support (which unfortunately is a funky level of if/and/but compatibility for what I’m looking to do).

That said, I tried this on my Unix box (compiled with OpenSSL support!), and it still did not return the cert headers via “fsockopen” (if there is a different function you’d recommend, let me know). I used it like this:

$fp = fsockopen(“ssl://login.yahoo.com”, 443, $errno, $errstr, $timeout=30);

It returned the same results as cURL (without verbose mode “on”).
Here is what cURL (and fsockopen) is returning via SSL (without verbose mode “on”):
>> curl -I https://login.yahoo.com

HTTP/1.0 200 OK
Date: Fri, 31 Oct 2003 17:18:11 GMT
P3P: policyref=“http://p3p.yahoo.com/w3c/p3p.xml”, CP=“CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV”
Cache-Control: private
Pragma: no-cache
Expires: Thu, 05 Jan 1995 22:00:00 GMT
Connection: close
Content-Type: text/html

This is cURL with verbose mode turned on:
>> curl -I -v https://login.yahoo.com

  • Connected to login1.login.vip.dcn.yahoo.com (216.109.127.60) port 443
  • SSL connection using EDH-RSA-DES-CBC3-SHA
  • Server certificate:
  •    subject: /C=US/ST=California/L=Santa Clara/O=Yahoo/OU=Yahoo/CN=login.yahoo.com
    
  •    start date: 2003-02-08 00:00:00 GMT
    
  •    expire date: 2004-02-08 23:59:59 GMT
    
  •    common name: login.yahoo.com (matched)
    
  •    issuer: /C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority
    

> HEAD / HTTP/1.1
User-Agent: curl/7.10.2 (i386-redhat-linux-gnu) libcurl/7.10.2 OpenSSL/0.9.6b ipv6 zlib/1.1.3
Host: login.yahoo.com
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, /

HTTP/1.0 200 OK
Date: Fri, 31 Oct 2003 17:18:36 GMT
P3P: policyref=“http://p3p.yahoo.com/w3c/p3p.xml”, CP=“CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV”
Cache-Control: private
Pragma: no-cache
Expires: Thu, 05 Jan 1995 22:00:00 GMT
Connection: close
Content-Type: text/html

  • Closing connection #0

It appears as if the “HEAD” or “header” only starts after the certificate, and that for whatever reason, this isn’t be returned in fsockopen.

I’ve been looking over all the comments on the function, and looking at the docs, and this seems like a perplexing bit of esoterica that I can’t seem to locate.
http://us4.php.net/manual/en/function.fsockopen.php

~ DNexus

Interesting, I personally haven’t ever tried to this sort of thing with SSL, I just use the Server variables PHP sends back to check whether the script is running over an SSL connection.

It makes sense that you just can’t open a socket to an SSL port, because of all of the security that SSL imposes.

Unfortunately, that’s where my knowledge on the subject ends. :slight_smile: I wish I could help you more.

Good Luck!