Skip to content

Commit 73781de

Browse files
timleggejonasbn
andauthored
Support to get SubjectAltNames easily (dsully#92)
* Support to get SubjectAltNames easily * Add missing Convert::ASN1 dependency * Apply suggestions from code review Co-authored-by: Jonas Brømsø <[email protected]> * Add constant for subjectaltname OID Co-authored-by: Jonas Brømsø <[email protected]>
1 parent 3875bca commit 73781de

File tree

5 files changed

+183
-0
lines changed

5 files changed

+183
-0
lines changed

Makefile.PL

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,7 @@ if ($Config::Config{myuname} =~ /sunos|solaris/i) {
4545
cc_optimize_flags($cc_option_flags);
4646
}
4747

48+
requires 'Convert::ASN1' => '0.33';
49+
4850
auto_install();
4951
WriteAll;

X509.pm

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use strict;
66
use Exporter;
77
use base qw(Exporter);
88

9+
use Convert::ASN1;
10+
911
our $VERSION = '1.911';
1012

1113
our @EXPORT_OK = qw(
@@ -83,6 +85,104 @@ sub Crypt::OpenSSL::X509::is_selfsigned {
8385
return $x509->subject eq $x509->issuer;
8486
}
8587

88+
sub Crypt::OpenSSL::X509::subjectaltname {
89+
my $x509 = shift;
90+
91+
my $SUBJECT_ALT_NAME_OID = '2.5.29.17';
92+
my $ext;
93+
eval {
94+
# extensions_by_oid croaks of no extensions found
95+
# we don't care we will return an empty array
96+
$ext = $x509->extensions_by_oid();
97+
};
98+
99+
# Determine whether the SubjectAltName exist
100+
if (! defined ${$ext}{$SUBJECT_ALT_NAME_OID}) {
101+
# Simply return a reference to an empty array if it does not exist
102+
my @tmp = ();
103+
return \@tmp;
104+
}
105+
106+
my $pdu = ${$ext}{$SUBJECT_ALT_NAME_OID}->value();
107+
108+
# remove leading '#' from the value returned
109+
$pdu =~ s/^#//g;
110+
111+
my $bin_data = join '', pack 'H*', $pdu;
112+
my $asn = Convert::ASN1->new();
113+
114+
my $ok = $asn->prepare(q<
115+
AnotherName ::= SEQUENCE {
116+
type OBJECT IDENTIFIER,
117+
value [0] EXPLICIT ANY } --DEFINED BY type-id }
118+
119+
EDIPartyName ::= SEQUENCE {
120+
nameAssigner [0] DirectoryString OPTIONAL,
121+
partyName [1] DirectoryString }
122+
123+
-- Directory string type --
124+
125+
DirectoryString ::= CHOICE {
126+
teletexString TeletexString, --(SIZE (1..MAX)),
127+
printableString PrintableString, --(SIZE (1..MAX)),
128+
bmpString BMPString, --(SIZE (1..MAX)),
129+
universalString UniversalString, --(SIZE (1..MAX)),
130+
utf8String UTF8String, --(SIZE (1..MAX)),
131+
ia5String IA5String --added for EmailAddress
132+
}
133+
134+
AttributeType ::= OBJECT IDENTIFIER
135+
136+
AttributeValue ::= DirectoryString --ANY
137+
138+
AttributeTypeAndValue ::= SEQUENCE {
139+
type AttributeType,
140+
value AttributeValue
141+
}
142+
143+
-- naming data types --
144+
145+
Name ::= CHOICE { -- only one possibility for now
146+
rdnSequence RDNSequence
147+
}
148+
149+
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
150+
151+
DistinguishedName ::= RDNSequence
152+
153+
RelativeDistinguishedName ::=
154+
SET OF AttributeTypeAndValue --SET SIZE (1 .. MAX) OF
155+
156+
SubjectAltName ::= GeneralNames
157+
158+
GeneralNames ::= SEQUENCE OF GeneralName
159+
160+
GeneralName ::= CHOICE {
161+
rfc822Name [1] IA5String,
162+
dNSName [2] IA5String,
163+
x400Address [3] ANY, --ORAddress,
164+
directoryName [4] Name,
165+
ediPartyName [5] EDIPartyName,
166+
uniformResourceIdentifier [6] IA5String,
167+
iPAddress [7] OCTET STRING,
168+
registeredID [8] OBJECT IDENTIFIER
169+
}
170+
171+
>);
172+
die '*** Could not prepare definition: '.$asn->error()
173+
if !$ok;
174+
175+
# This is an important bit - if you don't do the find the decode
176+
# will randomly fail/succeed. This is required to work
177+
my $asn_node = $asn->find('SubjectAltName')
178+
or die $asn->error;
179+
180+
my $san = $asn_node->decode($bin_data)
181+
or die 'Unable to decode SubjectAltName: '.$asn_node->error;
182+
183+
return $san;
184+
}
185+
86186
use XSLoader;
87187
XSLoader::load 'Crypt::OpenSSL::X509', $VERSION;
88188

certs/metacpan.pem

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIGWzCCBUOgAwIBAgIQAQP8uhTSO1GUfXeU8R9ZmTANBgkqhkiG9w0BAQsFADBY
3+
MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEuMCwGA1UE
4+
AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgSDIgMjAyMTAeFw0yMTEx
5+
MjYxOTQ2MDJaFw0yMjEyMjgxOTQ2MDFaMBcxFTATBgNVBAMMDG1ldGFjcGFuLm9y
6+
ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKrByUkP8INHaY8ei9Tw
7+
bFyhvMeTTcvSlwk7/lbZmxOCsCgMcGY5Qa4VVKNdW4WmwVz2Ix01sZ11Ny05/AUK
8+
az7Li8shZosr5FgBZRtigwG/aMSE9/m7YzkO4JrlNp+ZC0No6Rm+o3RZQckvpAEt
9+
OfSfM8mwUpwyyFaOQiaqDWrqdfLc57KxZ26JE1X2Zy8qd4WQt0opD3Gw69xbVSdD
10+
caZz4tulwgepdcynS1NskHkZRZUzeXF4aqETf5eo2uiumYczAwGvcXZXJbqmdwqr
11+
JlHyPMudcWt8iZZgNafvZDFqt1lpSzIPnxQ1MZJd2gKmIUQgMt5XdjoZeXmRcV+i
12+
lO0CAwEAAaOCA2AwggNcMBcGA1UdEQQQMA6CDG1ldGFjcGFuLm9yZzAOBgNVHQ8B
13+
Af8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQW
14+
BBSyXn9eVzsqF6MbGbwBGAs8EOJ++DBXBgNVHSAEUDBOMAgGBmeBDAECATBCBgor
15+
BgEEAaAyCgEDMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24u
16+
Y29tL3JlcG9zaXRvcnkvMAwGA1UdEwEB/wQCMAAwgZ4GCCsGAQUFBwEBBIGRMIGO
17+
MEAGCCsGAQUFBzABhjRodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9jYS9nc2F0
18+
bGFzcjNkdnRsc2NhaDIyMDIxMEoGCCsGAQUFBzAChj5odHRwOi8vc2VjdXJlLmds
19+
b2JhbHNpZ24uY29tL2NhY2VydC9nc2F0bGFzcjNkdnRsc2NhaDIyMDIxLmNydDAf
20+
BgNVHSMEGDAWgBQqNLmq+r88iPFH8tISeL7F5aqwaTBIBgNVHR8EQTA/MD2gO6A5
21+
hjdodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2NhL2dzYXRsYXNyM2R2dGxzY2Fo
22+
MjIwMjEuY3JsMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgBGpVXrdfqRIDC1
23+
oolp9PN9ESxBdL79SbiFq/L8cP5tRwAAAX1dyIXQAAAEAwBHMEUCIQDkBDN6Lj71
24+
RpdvqeH5BFzhlOT9p8wSzqyu1+QqhGopQAIgLYSjslyouTYGtxntvSF6Z4uHFmMI
25+
3e9siZRHIN2snNkAdgBRo7D1/QF5nFZtuDd4jwykeswbJ8v3nohCmg3+1IsF5QAA
26+
AX1dyIX5AAAEAwBHMEUCIQCRfynLHBESnWnvWPAYJW7UALG0VS0y3oSVWMbtALd2
27+
oQIgMkX97fszFH+03c3u3zp8kS0P1/xgzdFN1UaKeCEDNvsAdgBByMqx3yJGShDG
28+
oToJQodeTjGLGwPr60vHaPCQYpYG9gAAAX1dyIYtAAAEAwBHMEUCICljpiKvnaWk
29+
N7EL539adWwLt9QZkGWX0r7gmN9WbDn9AiEA1NGTWAuboP9hHszkioB5PnFSPMMA
30+
HbUWipsOA1zBDhQwDQYJKoZIhvcNAQELBQADggEBAKVjIn18TN/YGXE4xQ9A7pUz
31+
EC5vpROW2b0Ueq0O1kZmHo8K6J5thmbl9mujikb4eDF9xRctAaV4I3BxDt9esUUP
32+
vlBbYW2t7HcvaVpp0BnQpLNWNYbbfpYkZfwcoISmInsqDSFFR3ph5W3C4TWpJ82C
33+
H5JcSuabsbo/dGI7TqBh9CYqqp0rzOhkFzL/nAL9v3Q406Od7udYEzYgNT5Q8A2q
34+
rANtQZkhUq0Xa2yezjAzmxVDBKSTcRqDLwFkDlJx7epYfn731KdBqC21H8CY5fiS
35+
r7B4K8+gCBzWQqJGA9ZB9oVYbKvkBOLieijrcI8CTaxZ9x6/izI72r9nY8s+89A=
36+
-----END CERTIFICATE-----

certs/multiple-san-types.pem

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDVDCCAjygAwIBAgIUdVTWqZdp5RVv4KTws5uC2AQmXhMwDQYJKoZIhvcNAQEL
3+
BQAwGzELMAkGA1UEBhMCR0IxDDAKBgNVBAMMA2ZvbzAeFw0yMTEyMDQxNTMwMTJa
4+
Fw0yMjAxMDMxNTMwMTJaMBsxCzAJBgNVBAYTAkdCMQwwCgYDVQQDDANmb28wggEi
5+
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIh7BKjTlxpCY6rLhtZCmvy8Rv
6+
X6hcaQ6RMj6pMy57cAk2f7KK9jFKLPYF7PGsiemv3cQlxGV5R60vQ6gUABczKjYS
7+
8Kblqg6c61d0pn1nqZjbZ1F0ZLfncojWf1GZ+ZTqUAXrT3Uurl0FuzJ5UakN803b
8+
0Mudn0C9gXw/8E0w2N3aTR785MB+gRkaVB1qJJubI2LKsJ42wABB0isQ6wQusgUs
9+
F+AMQyepP1HJkt9uIPLb9gIUt4yVcmqdXTkJzTMNUqxDgVZa7IcHJBXO23ZIEr5c
10+
q6XzLesEM3jqcpqb5d7asVGkXVhUQSSDVQBVkBLs0uCzqGEpdXEHwMIVv1Z7AgMB
11+
AAGjgY8wgYwwHQYDVR0OBBYEFKsGJbRzbVn4zHHbeZipHrYB9/sPMB8GA1UdIwQY
12+
MBaAFKsGJbRzbVn4zHHbeZipHrYB9/sPMA8GA1UdEwEB/wQFMAMBAf8wJwYDVR0R
13+
BCAwHoIJZm9vLmNvLnVrgRF0aW1sZWdnZUBjcGFuLm9yZzAQBgNVHSAECTAHMAUG
14+
AyoDBDANBgkqhkiG9w0BAQsFAAOCAQEAEtEY4Ory9FL1zKCS2ez3ZZ3KVnhPLpdB
15+
T7uQu4tOvMgQj60S022AnQlVzc//97yBM/nj2D9b1PzTRdIH0hic8pP81MX6/rsv
16+
8QK1H8iQc5KGwt/Sg6pPTXOi+dZanpZ7chnxD98h2UjyONDLRCxoa+mhfwZTcF5w
17+
1Qz/wayxHQn91RUBCw0PcjLWJ/Sr+DlTrSsFfgDDhoSyBAhhG91DNobxAsrCjC2v
18+
pqvA0xL6uS44yHtOpwf8uG/TzaC1HoOgtqd8cZKCy7GH08EmJBLoQQJXG6ig/wjD
19+
EZ7IX0biRcHEXjaYhLCOysmGEJBwr+zioDjBV8CsbwoPe4TEZlnRLA==
20+
-----END CERTIFICATE-----

t/san.t

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use Test::More tests => 17;
2+
3+
BEGIN { use_ok('Crypt::OpenSSL::X509') };
4+
5+
my @files = <certs/*.pem>;
6+
foreach my $file (@files) {
7+
8+
if ($file eq 'certs/broken-utf8.pem') {
9+
next;
10+
}
11+
12+
ok(my $x509 = Crypt::OpenSSL::X509->new_from_file($file), 'new_from_file()');
13+
my $san = $x509->subjectaltname;
14+
15+
ok ($san, 'subjectaltname call succeeded');
16+
17+
# Mostly for debugging but this could be commented out
18+
foreach my $sanname (@$san) {
19+
for (keys %$sanname){
20+
print(" Found $_: ", $sanname->{$_}, "\n");
21+
}
22+
}
23+
}
24+
25+

0 commit comments

Comments
 (0)