Skip to content

Instantly share code, notes, and snippets.

@sharl
Created June 4, 2012 05:32
Show Gist options
  • Save sharl/2866528 to your computer and use it in GitHub Desktop.
Save sharl/2866528 to your computer and use it in GitHub Desktop.
Net::SSL::ExpireDate TLS patch
--- Net-SSL-ExpireDate-1.10/lib/Net/SSL/ExpireDate.pm 2011-03-16 13:01:58.000000000 +0900
+++ Net-SSL-ExpireDate-1.10_01/lib/Net/SSL/ExpireDate.pm 2012-06-04 14:17:21.000000000 +0900
@@ -4,7 +4,7 @@
use warnings;
use Carp;
-our $VERSION = '1.10';
+our $VERSION = '1.10_01';
use base qw(Class::Accessor);
use Crypt::OpenSSL::X509 qw(FORMAT_ASN1);
@@ -20,7 +20,7 @@
$Socket->require or die $@;
}
-__PACKAGE__->mk_accessors(qw(type target));
+__PACKAGE__->mk_accessors(qw(type target tls));
my $SSL3_RT_CHANGE_CIPHER_SPEC = 20;
my $SSL3_RT_ALERT = 21;
@@ -54,12 +54,15 @@
my $SSL3_AD_CERTIFICATE_UNKNOWN = 46;
my $SSL3_AD_ILLEGAL_PARAMETER = 47; # fatal
+my @starttls = qw(smtp pop3 imap ftp);
+
sub new {
my ($class, %opt) = @_;
my $self = bless {
type => undef,
target => undef,
+ tls => $opt{tls},
expire_date => undef,
timeout => undef,
}, $class;
@@ -92,10 +95,96 @@
$port ||= 443;
### $host
### $port
+ my ($begin_date_str, $expire_date_str);
+ if ($self->{tls}) {
+ my $re = join('|', @starttls);
+ if ($self->{tls} =~ /^$re$/io) {
+ my $sock = IO::Socket::INET->new(PeerAddr => $host,
+ PeerPort => $port,
+ Proto => 'tcp',
+ Timeout => $self->{timeout}) or croak "Connection failed: $@";
+ if ($self->{tls} =~ /^smtp$/io) {
+ sub _smtp_response {
+ my $sock = shift;
+ my $line = $sock->getline();
+ my @rsp = $line =~ /^(\d+)(.)([^\r]*)/o;
+ return ($rsp[0], $rsp[2], $rsp[1]);
+ }
+
+ my ($num, $txt, $more) = _smtp_response($sock);
+ if ($num != 220) {
+ croak "Connection failed: $txt";
+ }
+ $sock->printf("EHLO localhost\r\n");
+ ($num, $txt, $more) = _smtp_response($sock);
+ if ($num != 250) {
+ croak "EHLO failed";
+ }
+ while ($more eq '-') {
+ ($num, $txt, $more) = _smtp_response($sock);
+ }
+ $sock->printf("STARTTLS\r\n");
+ ($num, $txt, $more) = _smtp_response($sock);
+ if ($num != 220) {
+ croak "Invalid response for STARTTLS: $num $txt";
+ }
+ } elsif ($self->{tls} =~ /^pop3$/io) {
+ my $line;
+ $line = $sock->getline();
+ if ($line !~ /^\+OK/o) {
+ croak "Connection failed: $line";
+ }
+ $sock->printf("STLS\r\n");
+ $line = $sock->getline();
+ if ($line !~ /^\+OK/o) {
+ croak "Invalid response for STLS: $line";
+ }
+ } elsif ($self->{tls} =~ /^imap$/io) {
+ my $line;
+ $line = $sock->getline();
+ if ($line !~ /^. OK/o) {
+ croak "Connection failed: $line";
+ }
+ $sock->printf(". CAPABILITY\r\n");
+ while ($line = $sock->getline()) {
+ last if $line =~ /^\./o;
+ }
+ $sock->printf(". STARTTLS\r\n");
+ $line = $sock->getline();
+ if ($line !~ /^\. OK/o) {
+ croak "Invalid response for STARTTLS: $line";
+ }
+ } elsif ($self->{tls} =~ /^ftp$/io) {
+ my $line;
+ $line = $sock->getline();
+ if ($line !~ /^220/o) {
+ croak "Connection failed: $line";
+ }
+ $sock->printf("AUTH TLS\r\n");
+ $line = $sock->getline();
+ if ($line !~ /^234/o) {
+ croak "Invalid response for AUTH TLS: $line";
+ }
+ }
+ use IO::Socket::SSL;
+ my $tls = IO::Socket::SSL->start_SSL($sock, SSL_version => 'TLSv1');
+ if (! $tls) {
+ croak "Couldn't start TLS: " . IO::Socket::SSL::errstr;
+ }
+ my $cert = $tls->peer_certificate();
+
+ use Net::SSLeay;
+ $expire_date_str = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter ($cert));
+ $begin_date_str = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($cert));
+ } else {
+ croak "unknown tls: '$self->{tls}'. tls is only " . join(', ', @starttls);
+ }
+ } else {
my $cert = _peer_certificate($host, $port, $self->{timeout});
my $x509 = Crypt::OpenSSL::X509->new_from_string($cert, FORMAT_ASN1);
- my $begin_date_str = $x509->notBefore;
- my $expire_date_str = $x509->notAfter;
+ $begin_date_str = $x509->notBefore;
+ $expire_date_str = $x509->notAfter;
+ }
$self->{expire_date} = DateTime->from_epoch(epoch => str2time($expire_date_str));
$self->{begin_date} = DateTime->from_epoch(epoch => str2time($begin_date_str));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment