Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easily accessing "X509v3 Subject Alternative Name" #50

Closed
Athanasius opened this issue Feb 9, 2016 · 5 comments · Fixed by #92
Closed

Easily accessing "X509v3 Subject Alternative Name" #50

Athanasius opened this issue Feb 9, 2016 · 5 comments · Fixed by #92
Assignees
Milestone

Comments

@Athanasius
Copy link

Am I missing something or is the best you can do:

my $x509 = Crypt::OpenSSL::X509->new_from_file($d . "/fullchain.pem");
if ($x509->has_extension_oid('2.5.29.17')) {
  my $ext = $x509->extensions_by_oid();
  print ${$ext}{'2.5.29.17'}->value(), "\n";
}

which in my case results in "0...www.fysh.org..fysh.org" being printed due to "FIXME: the value is returned as a string but may represent a complex object." ?

So I'm going to have to munge that string back into the list of alternate names, rather than have an object handed to me that I can somehow iterate over. I did try $x509->subject_name(), but that doesn't contain the alternates, i.e. the following prints "$subject_alternate_name = -1":

    my $subject_name = $x509->subject_name();
    my $subject_alternate_name = $subject_name->get_index_by_oid_type('2.5.29.17');
    print "\$subject_alternate_name = ", $subject_alternate_name, "\n";
@Athanasius
Copy link
Author

And that stringified object isn't even in any way consistent. I get "$VAR1 = '0...www.fysh.org..fysh.org';" for one and yet "$VAR1 = '03..squirrelmail.fysh.org';sm.fysh.org." for another, and "$VAR1 = '0..\rmail.fysh.org';" for yet another (using Data::Dumper there, and explicitly put the \r in the last one myself).

So, is there a way to consistently turn that string back into some sort of object, even just an array ?

@Athanasius
Copy link
Author

I can see that the C .xs code is doing:

  ASN1_STRING_print(bio, X509_EXTENSION_get_data(ext));

so thought perhaps Convert::ASN1 would help, but it doesn't seem to handle such strings either. Maybe I'm missing some trick with unpack() ? For now I've figured out that the two characters before each entry match /.[.\r]/, at least for my examples so far.

@cbiedl
Copy link

cbiedl commented May 23, 2017

Tough luck. Problem is, the ASN1_STRING_print function used by value replaces unprintable characters with '.', thus destroying the asn1 data the value consists of.

Therefore I strongly suggest to create a new function value_raw (or change the behaviour of value at the risk of an API break) to use ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ext), 0); instead so this mangling so longer happens. (The third parameter flags needs a re-visit first.)

After that, the resulting data still at least valid asn1. However, Convert::ASN1 still cannot deal with it for reasons I fail to understand.

@ikedas
Copy link
Contributor

ikedas commented Jun 17, 2021

This issue seems to have been solved to some extent by ac9f148.

@jonasbn jonasbn self-assigned this Aug 1, 2021
@timlegge
Copy link
Contributor

timlegge commented Dec 3, 2021

I was looking at https://stackoverflow.com/questions/70174655/how-to-properly-obtain-san-using-perl-library-cryptopensslx509

It took me a while but I did figure it out:

use Crypt::OpenSSL::X509;
use Convert::ASN1;
 
my $x509 = Crypt::OpenSSL::X509->new_from_file('google.pem');
my $ext = $x509->extensions_by_oid();
my $pdu = ${$ext}{'2.5.29.17'}->value();
$pdu =~ s/#//g;

my @san = get_san($pdu);

print "Size: ", scalar @san, "\n";

foreach (@san) {
    print "$_\n";
}

sub get_san {
    my $bin_data = join '', pack 'H*', @_;
    $asn = Convert::ASN1->new();

    my $ok = $asn->prepare(q<
        DNSName ::=  
            [2]
            IA5String
        SubjectAltName ::= SEQUENCE OF
            DNSName
    >);
    die "*** Could not prepare definition: ".$asn->error()
        if !$ok;

    my $top = $asn->find("SubjectAltName")
        or die $asn->error;
    $out = $top->decode($bin_data)
        or die "can't decode Contact: ".$top->error;

    return @$out;
}

@jonasbn jonasbn added this to the 1.9.11 milestone Jan 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants