Subject: | CERT_asHash() subjectAltNames incorrectly formats IPv6 address |
Trying to obtain subjectAltNames of our LDAP server's certificate
in human-readable form using the following code snippet:
my $cert_obj = $client->peer_certificate;
my $cert = CERT_asHash($cert_obj);
printf("%s -> %s\n", @$_) for @{$cert->{subjectAltNames}};
which produces:
IP -> 127.0.0.1
IP -> 0:0:0:1
DNS -> localhost
DNS -> localhost.localdomain
IP -> 193.2.4.14
IP -> 193.2.4.36
IP -> 20011470:ff800000:0:3890001
IP -> 20011470:ff800000:0:3890002
IP -> 20011470:ff800000:0:18120001
DNS -> ldap.ijs.si
DNS -> ldap2.ijs.si
As you can see IPv6 addresses are formatted incorrectly:
instead of 8 16-bit sections delimited by colons,
one ends up with 4 32-bit sections, which is not a valid
syntax for an IPv6 address.
The culprit is in IO/Socket/SSL/Utils.pm, sub CERT_asHash() :
} elsif ( length($v) == 16 ) {
$v = join(':',map { sprintf( "%x",$_) } unpack("NNNN",$v));
which should have been something like:
} elsif ( length($v) == 16 ) {
$v = join(':',map { sprintf( "%x",$_) } unpack("n8",$v));
which produces a correct formatting. It would be even nicer
to obtain a "zero-compressed form", although a "preferred form"
is fine too.
Using IO::Socket::SSL::Utils 2.014 (that comes with IO::Socket::SSL 2.021),
perl 5.22. Attached is a certificate which demonstrates the problem.
Subject: | 0.pem |
Message body not shown because it is not plain text.