I've had some code running for the past few years that reports if the a given domain's SSL certificate is invalid. Recently I've come across one domain where it is telling me that the cert is invalid, but in reality the certificate is perfectly fine (as far as I can tell). I was hoping a few eyes on this could find the problem I've been missing. Here is the code:
#!/usr/bin/perl checkCert('www.clevelandorchestra.com',''); ## Verify the SSL certificate of the given path sub checkCert { my ($host, $port) = @_; ## Get the host domain and port from the path $port = $port ? $port : '443'; $ENV{HTTPS_CA_FILE} = 'cacert.pem'; my $cert_error_message = ''; ## Create the connection to the server. require Net::SSL; my $sock; eval { $sock = Net::SSL->new(PeerAddr => $host, PeerPort => $port, Ti +meout => 5); }; ## If we are unable to connect, give an error. This also may ## mean the certificate authority is invalid. ## Check #1: Valid CA if($@) { $cert_error_message = "SSL certificate invalid or is not from +a trusted source: $@"; $cert_error_message =~ s/ at .+$//s; } else { ## Check #2: Domain matches CN ## Check that the domain name matched the certificate common n +ame my $cert = $sock->get_peer_certificate; my $subject = $cert->subject_name; $subject =~ s/\*//g; # Remove wildcard astricks my ($CN) = $subject =~ /CN=(.*)\W/; if(!$CN) { $cert_error_message = "Unable to read SSL certificate"; } elsif($host !~ /$CN/i) { $cert_error_message = "SSL Certificate Common Name mismatc +h. Retrieved common name '$CN' does not match hostname '$h ost'"; } ## Check #3: Check for expired my $startsOn = getSSLTime($cert->not_before); my $expiresOn = getSSLTime($cert->not_after); my $currTime = time; ## Check that the certificate start time is not after the curr +ent time if($currTime < $startsOn) { $cert_error_message = "SSL Certificate is not valid before + ". $cert->not_before; } if($currTime > $expiresOn) { $cert_error_message = "SSL Certificate has expired, not va +lid after ". $cert->not_after; } } ## If we found an error, set the global error message string and s +ignal there was an error if($cert_error_message) { print "$cert_error_message at $host:$por +t\n"; } else { print "SUCCESS: SSL Cerificate verified\n"; } delete $ENV{HTTPS_CA_FILE}; return 1; } ## Given a string in the format '$year-$month-$day $hour:$minute:$seco +nd', return ## the epoch time in GMT time. ## Used by checkCert. sub getSSLTime { my ($string) = @_; require Time::Local; my ($year, $month, $day, $hour, $minute,$second,$GMT) = $string =~ + /^(.+)-(.+)-(.+) (.+):(.+):(\S+)( GMT)?$/; $year -= 1900; $month--; return Time::Local::timegm($second,$minute,$hour,$day,$month,$year +); }
You can put in any other domain that works over https and it works great. This specific domain though is what baffles me. Note for the cacert.pem file, I've been using: http://curl.haxx.se/ca/cacert.pem Note that I would really like to keep this code as unchanged as possible. It's been battle tested fairly well over the past few years, and so I'm hoping there's a small fix I can add that would allow me to keep most of the logic. Thanks to everyone in advance!

In reply to Checking the validity of an SSL cert by lennysan

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.