perlopenssl

Net::SSLeay issue with time functions


use Net::SSLeay qw(get_https3);
use DateTime;

my $domain = 'google.com';
my ($page, $response, $headers, $cert, $err, $status) = Net::SSLeay::get_https3($domain, 443, '/');

            my $issuer = Net::SSLeay::X509_get_issuer_name($cert);
            my $issuer_cn = Net::SSLeay::X509_NAME_get_text_by_NID($issuer, Net::SSLeay::NID_commonName());
            my $not_after = Net::SSLeay::X509_get_notAfter($cert);
            my $valid_until = Net::SSLeay::P_ASN1_TIME_get_isotime($not_after);
            my $dt = DateTime->from_epoch(epoch => Net::SSLeay::P_ASN1_TIME_get_secs($not_after));

print $dt->strftime('%F %T %Z');

running this gives error:

Can't locate auto/Net/SSLeay/P_ASN1_TIME.al in @INC (@INC contains: /usr/local/lib64/perl5/5.32 /usr/local/share/perl5/5.32 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5) at /tmp/a.pl line 13.

I have tried compiling openssl from source and reinstalling Net::SSLeay but doesn't help. Here's Openssl version info:

perl -MNet::SSLeay -e 'print Net::SSLeay::SSLeay_version(), "\n"'
OpenSSL 3.2.2 4 Jun 2024

Solution

  • As Steffen mentioned, P_ASN1_TIME_get_secs, isn't a real function. You can achieve what you're after using DateTime::Format::ISO8601, to parse the ISO time returned by P_ASN1_TIME_get_isotime into a Perl DateTime object.

    Install from the CPAN:

    cpan -I DateTime::Format::ISO8601
    

    Adjust your code to use it:

    use Net::SSLeay qw(get_https3);
    use DateTime;
    use DateTime::Format::ISO8601;
    use Carp 'croak';
    
    my $domain = 'google.com';
    my ($page, $response, $headers, $cert, $err, $status) = Net::SSLeay::get_https3($domain, 443, '/');
    
    my $issuer = Net::SSLeay::X509_get_issuer_name($cert);
    my $issuer_cn = Net::SSLeay::X509_NAME_get_text_by_NID($issuer, Net::SSLeay::NID_commonName());
    my $not_after = Net::SSLeay::X509_get_notAfter($cert);
    my $valid_until = Net::SSLeay::P_ASN1_TIME_get_isotime($not_after);
    
    # P_ASN1_TIME_get_isotime can return '' if it fails
    if (!$valid_until) {
        croak "not_after was invalid, or something went wrong: '$not_after'";
    }
    
    my $dt = DateTime::Format::ISO8601->parse_datetime($valid_until);
    
    print $dt->strftime('%F %T %Z');