line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package VOMS::Lite::AC; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
18
|
use 5.004; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
42
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
247
|
|
5
|
1
|
|
|
1
|
|
7
|
use Time::Local; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
66
|
|
6
|
1
|
|
|
1
|
|
5
|
use VOMS::Lite::ASN1Helper qw(ASN1Unwrap ASN1OIDtoOID Hex DecToHex ASN1BitStr ASN1Wrap ASN1Index); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
80
|
|
7
|
1
|
|
|
1
|
|
5
|
use VOMS::Lite::CertKeyHelper qw(digestSign buildchain); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
47
|
|
8
|
1
|
|
|
1
|
|
4
|
use VOMS::Lite::PEMHelper qw(readCert); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
40
|
|
9
|
1
|
|
|
1
|
|
5
|
use VOMS::Lite::X509; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
54
|
|
10
|
1
|
|
|
1
|
|
6
|
use VOMS::Lite::KEY; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
44
|
|
11
|
1
|
|
|
1
|
|
7
|
use Sys::Hostname; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
60
|
|
12
|
|
|
|
|
|
|
#use Regexp::Common qw (URI); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
require Exporter; |
15
|
1
|
|
|
1
|
|
14
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6248
|
|
16
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
$VERSION = '0.20'; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
############################################# |
21
|
|
|
|
|
|
|
sub Examine { |
22
|
0
|
|
|
0
|
0
|
0
|
my ($decoded,$dataref)=@_; |
23
|
0
|
0
|
|
|
|
0
|
$dataref={Start=>"",End=>"",FQANs=>"",IssuerDN=>"",HolderIssuerDN=>"",VOMSDIR=>"/etc/grid-security/vomsdir"} if( ! defined $dataref ); |
24
|
0
|
|
|
|
|
0
|
my %Values=%$dataref; |
25
|
0
|
|
|
|
|
0
|
my @ASN1Index=ASN1Index($decoded); |
26
|
0
|
|
|
|
|
0
|
my @Values; |
27
|
0
|
0
|
|
|
|
0
|
return ( {Errors=>"Unable to parse attribute certificate"} ) if (@ASN1Index==0); |
28
|
|
|
|
|
|
|
|
29
|
0
|
|
|
|
|
0
|
my ($index,$ignoreuntil)=(0,0); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Drill down into the certificate |
32
|
0
|
|
|
|
|
0
|
shift @ASN1Index; # skip the wrapping of the attribute certificate sequence |
33
|
0
|
|
|
|
|
0
|
shift @ASN1Index; # skip the wrapping of the bundle of atribute certificate sequence |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Get each AC |
36
|
0
|
|
|
|
|
0
|
my @ACs; |
37
|
0
|
|
|
|
|
0
|
foreach (@ASN1Index) { |
38
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @$_; |
39
|
0
|
0
|
|
|
|
0
|
if ( $HEADSTART < $ignoreuntil ) { next; } |
|
0
|
|
|
|
|
0
|
|
40
|
|
|
|
|
|
|
else { |
41
|
0
|
|
|
|
|
0
|
push @ACs,[$CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN]; |
42
|
0
|
|
|
|
|
0
|
$ignoreuntil=$HEADSTART+$HEADLEN+$CHUNKLEN; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
0
|
foreach (@ACs) { |
47
|
0
|
|
|
|
|
0
|
my %LocalValues; |
48
|
0
|
|
|
|
|
0
|
my ($ACversion,$ACholder,$ACissuer,$ACalgorithmId,$ACSerial,$ACvalidity,$ACattribute,$ACUniqueId,$ACExtensions,$ACSignatureType,$ACSignature); |
49
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=@$_; |
50
|
0
|
|
|
|
|
0
|
my ($TBSAC,$SIGType,$SIG); |
51
|
0
|
|
|
|
|
0
|
$ignoreuntil=$HEADSTART+$HEADLEN; |
52
|
0
|
|
|
|
|
0
|
my $ignoreafter=$HEADSTART+$HEADLEN+$CHUNKLEN; |
53
|
0
|
|
|
|
|
0
|
my $index=0; |
54
|
0
|
|
|
|
|
0
|
my $SIGSTART; |
55
|
0
|
|
|
|
|
0
|
foreach (@ASN1Index) { |
56
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @$_; |
57
|
0
|
0
|
|
|
|
0
|
if ( $HEADSTART < $ignoreuntil ) { next; } |
|
0
|
0
|
|
|
|
0
|
|
58
|
0
|
|
|
|
|
0
|
elsif ( $HEADSTART >= $ignoreafter ) { last; } |
59
|
|
|
|
|
|
|
else { |
60
|
0
|
0
|
0
|
|
|
0
|
if ($index==0) { $TBSAC = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN)); $index++; $SIGSTART=$HEADSTART+$HEADLEN+$CHUNKLEN; next;} #this is a container |
|
0
|
0
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
61
|
0
|
|
|
|
|
0
|
elsif ($index==1) { $ACversion = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
62
|
0
|
|
|
|
|
0
|
elsif ($index==2) { $ACholder = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
63
|
0
|
|
|
|
|
0
|
elsif ($index==3) { $ACissuer = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
64
|
0
|
|
|
|
|
0
|
elsif ($index==4) { $ACalgorithmId = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
65
|
0
|
|
|
|
|
0
|
elsif ($index==5) { $ACSerial = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
66
|
0
|
|
|
|
|
0
|
elsif ($index==6) { $ACvalidity = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));;} |
67
|
0
|
|
|
|
|
0
|
elsif ($index==7) { $ACattribute = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
68
|
0
|
|
|
|
|
0
|
elsif ($index==8 && $HEADSTART < $SIGSTART) { $ACExtensions = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
|
0
|
|
|
|
|
0
|
|
69
|
0
|
|
|
|
|
0
|
elsif ($index==8) {$index++; next;} |
70
|
0
|
|
|
|
|
0
|
elsif ($index==9) { $ACSignatureType = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN));} |
71
|
0
|
|
|
|
|
0
|
elsif ($index==10){ $ACSignature = substr($decoded,$HEADSTART,($HEADLEN+$CHUNKLEN)); last;} |
|
0
|
|
|
|
|
0
|
|
72
|
0
|
|
|
|
|
0
|
$index++; |
73
|
0
|
|
|
|
|
0
|
$ignoreuntil=$HEADSTART+$HEADLEN+$CHUNKLEN; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
# Extract the main components of the Attribute Certificate |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
#Standard |
79
|
0
|
0
|
|
|
|
0
|
if (defined $Values{TBSAC}) {$LocalValues{TBSAC}=$TBSAC;} |
|
0
|
|
|
|
|
0
|
|
80
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACversion}) {$LocalValues{ACversion}=$ACversion;} |
|
0
|
|
|
|
|
0
|
|
81
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACholder}) {$LocalValues{ACholder}=$ACholder;} |
|
0
|
|
|
|
|
0
|
|
82
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACissuer}) {$LocalValues{ACissuer}=$ACissuer;} |
|
0
|
|
|
|
|
0
|
|
83
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACalgorithmId}) {$LocalValues{ACalgorithmId}=$ACalgorithmId;} |
|
0
|
|
|
|
|
0
|
|
84
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACSerial}) {$LocalValues{ACSerial}=$ACSerial;} |
|
0
|
|
|
|
|
0
|
|
85
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACvalidity}) {$LocalValues{ACvalidity}=$ACvalidity;} |
|
0
|
|
|
|
|
0
|
|
86
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACattribute}) {$LocalValues{ACattribute}=$ACattribute;} |
|
0
|
|
|
|
|
0
|
|
87
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACExtensions}) {$LocalValues{ACExtensions}=$ACExtensions;} |
|
0
|
|
|
|
|
0
|
|
88
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACSignatureType}) {$LocalValues{ACSignatureType}=$ACSignatureType;} |
|
0
|
|
|
|
|
0
|
|
89
|
0
|
0
|
|
|
|
0
|
if (defined $Values{ACSignature}) {$LocalValues{ACSignature}=$ACSignature;} |
|
0
|
|
|
|
|
0
|
|
90
|
|
|
|
|
|
|
|
91
|
0
|
0
|
|
|
|
0
|
if ($ACExtensions ne "" ) { |
92
|
0
|
|
|
|
|
0
|
my @ACExtensionIndex=ASN1Index($ACExtensions); |
93
|
0
|
|
|
|
|
0
|
shift @ACExtensionIndex; #Unwrap extensions; |
94
|
0
|
|
|
|
|
0
|
while (@ACExtensionIndex) { |
95
|
0
|
|
|
|
|
0
|
my $Seqref=shift(@ACExtensionIndex); |
96
|
0
|
|
|
|
|
0
|
my $OIDref=shift(@ACExtensionIndex); |
97
|
0
|
|
|
|
|
0
|
my $OSref=shift(@ACExtensionIndex); |
98
|
0
|
0
|
|
|
|
0
|
my $Critical=( $OSref =~ /\x01\x01[^\0]/ )?1:0; |
99
|
0
|
0
|
|
|
|
0
|
$OSref=shift(@ACExtensionIndex) if ($Critical); |
100
|
0
|
|
|
|
|
0
|
my $OID=substr($ACExtensions,(${ $OIDref }[3]+${ $OIDref }[4]),${ $OIDref }[5]); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
101
|
0
|
|
|
|
|
0
|
my $OIDstr=ASN1OIDtoOID($OID); |
102
|
0
|
0
|
0
|
|
|
0
|
if($OIDstr eq "2.5.29.56" && defined $Values{'noRevAvail'}) { |
103
|
0
|
|
|
|
|
0
|
$LocalValues{noRevAvail} = "\x01"; |
104
|
|
|
|
|
|
|
} |
105
|
0
|
0
|
0
|
|
|
0
|
if($OIDstr eq "2.5.29.35" && defined $Values{'authorityKeyIdentifier'}) { |
106
|
0
|
|
|
|
|
0
|
my $AKI=substr($ACExtensions,(${ $OSref }[3]+${ $OSref }[4]),${ $OSref }[5]); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
107
|
0
|
|
|
|
|
0
|
$AKI=ASN1Unwrap($AKI); |
108
|
0
|
|
|
|
|
0
|
$LocalValues{authorityKeyIdentifier}=$AKI; |
109
|
0
|
|
|
|
|
0
|
$LocalValues{authorityKeyIdentifierSkid} = undef; #explicitly undefine these incase they were set in the call! |
110
|
0
|
|
|
|
|
0
|
$LocalValues{authorityKeyIdentifierIssuer} = undef; # |
111
|
0
|
|
|
|
|
0
|
$LocalValues{authorityKeyIdentifierSerial} = undef; # |
112
|
0
|
|
|
|
|
0
|
until (length($AKI) == 0) { |
113
|
0
|
|
|
|
|
0
|
my ($headlen,$reallen,$Class,$Constructed,$Tag,$str)=ASN1Unwrap($AKI); |
114
|
0
|
|
|
|
|
0
|
$AKI=substr($AKI,($headlen+$reallen)); |
115
|
0
|
0
|
|
|
|
0
|
if ($Tag==0) {$LocalValues{authorityKeyIdentifierSkid}=$str;} |
|
0
|
0
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
116
|
0
|
|
|
|
|
0
|
elsif ($Tag==1) {$LocalValues{authorityKeyIdentifierIssuer}=$str;} |
117
|
|
|
|
|
|
|
elsif ($Tag==2) {$LocalValues{authorityKeyIdentifierSerial}=Hex($str);} |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
} |
120
|
0
|
0
|
0
|
|
|
0
|
if($OIDstr eq "1.3.6.1.4.1.8005.100.100.11" && defined $Values{'vOMSTags'} ) { |
121
|
0
|
|
|
|
|
0
|
$LocalValues{vOMSTags}=substr($ACExtensions,(${ $OSref }[3]+${ $OSref }[4]),${ $OSref }[5]); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
122
|
|
|
|
|
|
|
} |
123
|
0
|
0
|
0
|
|
|
0
|
if($OIDstr eq "1.3.6.1.4.1.8005.100.100.10" && ( defined $Values{'vOMSACCertList'} || defined $Values{Verify} ) ) { |
|
|
|
0
|
|
|
|
|
124
|
0
|
|
|
|
|
0
|
my $SEQ=ASN1Unwrap(substr($ACExtensions,(${ $OSref }[3]+${ $OSref }[4]),${ $OSref }[5])); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
125
|
0
|
|
|
|
|
0
|
my @DERs; |
126
|
0
|
|
|
|
|
0
|
until (length($SEQ) == 0) { |
127
|
0
|
|
|
|
|
0
|
my ($headlen,$reallen,$Class,$Constructed,$Tag,$cert)=ASN1Unwrap($SEQ); |
128
|
0
|
|
|
|
|
0
|
$SEQ=substr($SEQ,($headlen+$reallen)); |
129
|
0
|
|
|
|
|
0
|
push @DERs,$cert; |
130
|
|
|
|
|
|
|
} |
131
|
0
|
|
|
|
|
0
|
$LocalValues{vOMSACCertList} = \@DERs; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
#Deep |
137
|
0
|
0
|
|
|
|
0
|
if (defined $Values{Version} ) { |
138
|
0
|
|
|
|
|
0
|
$LocalValues{Version} = ASN1Unwrap($ACversion); |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
#To whom does the AC belong |
142
|
0
|
0
|
0
|
|
|
0
|
if ( defined $Values{HolderIssuerDN} || defined $Values{HolderSerial} ) { |
143
|
0
|
|
|
|
|
0
|
$Values{HolderSerial}=""; $Values{HolderIssuerDN}=""; # one doesn't make sense without the other makesure both are set |
|
0
|
|
|
|
|
0
|
|
144
|
0
|
|
|
|
|
0
|
my $a0=ASN1Unwrap($ACholder); |
145
|
0
|
|
|
|
|
0
|
my $SEQ=ASN1Unwrap($a0); |
146
|
0
|
|
|
|
|
0
|
my ($headlen,$reallen,$Class,$Constructed,$Tag,$name)=ASN1Unwrap($SEQ); |
147
|
0
|
|
|
|
|
0
|
my $int=ASN1Unwrap(substr($SEQ,($headlen+$reallen))); |
148
|
0
|
|
|
|
|
0
|
$SEQ=ASN1Unwrap($name); |
149
|
0
|
|
|
|
|
0
|
my @rdns=ASN1Index($SEQ); |
150
|
0
|
|
|
|
|
0
|
while (@rdns) { |
151
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=(0,0,0,0,0); |
152
|
0
|
|
|
|
|
0
|
until ($TAG == 6 ) { ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @rdns}; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
153
|
0
|
|
|
|
|
0
|
my $OID=substr($SEQ,($HEADSTART+$HEADLEN),$CHUNKLEN); |
154
|
0
|
|
|
|
|
0
|
($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @rdns}; |
|
0
|
|
|
|
|
0
|
|
155
|
0
|
|
|
|
|
0
|
my $Value=substr($SEQ,($HEADSTART+$HEADLEN),$CHUNKLEN); |
156
|
0
|
|
|
|
|
0
|
$LocalValues{HolderIssuerDN}.="/".VOMS::Lite::CertKeyHelper::OIDtoDNattrib(ASN1OIDtoOID($OID))."=$Value"; |
157
|
|
|
|
|
|
|
} |
158
|
0
|
|
|
|
|
0
|
$LocalValues{HolderSerial} = "0x".Hex($int); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Who was the Issuer |
162
|
0
|
0
|
0
|
|
|
0
|
if ( defined $Values{IssuerDN} || defined $Values{Verify}) { |
163
|
0
|
|
|
|
|
0
|
my $SEQ=ASN1Unwrap($ACissuer); |
164
|
0
|
|
|
|
|
0
|
my $name=ASN1Unwrap($SEQ); |
165
|
0
|
|
|
|
|
0
|
$SEQ=ASN1Unwrap($name); |
166
|
0
|
|
|
|
|
0
|
my @rdns=ASN1Index($SEQ); |
167
|
0
|
|
|
|
|
0
|
while (@rdns) { |
168
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=(0,0,0,0,0); |
169
|
0
|
|
|
|
|
0
|
until ($TAG == 6 ) { ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @rdns}; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
170
|
0
|
|
|
|
|
0
|
my $OID=substr($SEQ,($HEADSTART+$HEADLEN),$CHUNKLEN); |
171
|
0
|
|
|
|
|
0
|
($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @rdns}; |
|
0
|
|
|
|
|
0
|
|
172
|
0
|
|
|
|
|
0
|
my $Value=substr($SEQ,($HEADSTART+$HEADLEN),$CHUNKLEN); |
173
|
0
|
|
|
|
|
0
|
$LocalValues{IssuerDN}.="/".VOMS::Lite::CertKeyHelper::OIDtoDNattrib(ASN1OIDtoOID($OID))."=$Value"; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# What was/were the Attribute(s) |
178
|
0
|
0
|
0
|
|
|
0
|
if ( defined $Values{PA} || defined $Values{FQANs} ) { |
179
|
0
|
|
|
|
|
0
|
my @AttrIndex=ASN1Index($ACattribute); |
180
|
0
|
|
|
|
|
0
|
my @Attrs; |
181
|
|
|
|
|
|
|
my $PA; |
182
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=(0,0,-1,0,0); |
183
|
0
|
|
0
|
|
|
0
|
until ($CLASS==2 && $TAG == 6 ) { ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @AttrIndex}; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
184
|
0
|
|
|
|
|
0
|
$PA=substr($ACattribute,($HEADSTART+$HEADLEN),$CHUNKLEN); |
185
|
0
|
|
|
|
|
0
|
while (@AttrIndex) { |
186
|
0
|
|
|
|
|
0
|
my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=(0,0,-1,0,0); |
187
|
0
|
|
0
|
|
|
0
|
until ($CLASS==0 && $TAG == 4 ) { ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @AttrIndex}; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
188
|
0
|
|
|
|
|
0
|
my $Value=substr($ACattribute,($HEADSTART+$HEADLEN),$CHUNKLEN); |
189
|
0
|
|
|
|
|
0
|
push @Attrs,$Value; |
190
|
|
|
|
|
|
|
} |
191
|
0
|
|
|
|
|
0
|
$LocalValues{PA}=$PA; |
192
|
0
|
|
|
|
|
0
|
$LocalValues{FQANs}=\@Attrs; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# Values of Start and End Time Seconds since Epoch |
196
|
0
|
0
|
0
|
|
|
0
|
if (defined $Values{Start} || defined $Values{End}) { |
197
|
0
|
|
|
|
|
0
|
my @validity=ASN1Unwrap($ACvalidity); |
198
|
0
|
|
|
|
|
0
|
my @st=ASN1Unwrap($validity[5]); |
199
|
0
|
|
|
|
|
0
|
my @et=ASN1Unwrap(substr($validity[5],$st[0]+$st[1])); |
200
|
0
|
0
|
0
|
|
|
0
|
if ( $st[4] eq "23" && $st[5]=~ /^(..)(..)(..)(..)(..)(..)Z$/ ) { $LocalValues{Start} = timegm($6,$5,$4,$3,($2-1),$1); } |
|
0
|
0
|
0
|
|
|
0
|
|
201
|
0
|
|
|
|
|
0
|
elsif ( $st[4] eq "24" && $st[5]=~ /^(....)(..)(..)(..)(..)(..)Z$/ ) { $LocalValues{Start} = timegm($6,$5,$4,$3,($2-1),$1); } |
202
|
0
|
0
|
0
|
|
|
0
|
if ( $et[4] eq "23" && $et[5]=~ /^(..)(..)(..)(..)(..)(..)Z$/ ) { $LocalValues{End} = timegm($6,$5,$4,$3,($2-1),$1); } |
|
0
|
0
|
0
|
|
|
0
|
|
203
|
0
|
|
|
|
|
0
|
elsif ( $et[4] eq "24" && $et[5]=~ /^(....)(..)(..)(..)(..)(..)Z$/ ) { $LocalValues{End} = timegm($6,$5,$4,$3,($2-1),$1); } |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# Signature Value |
207
|
0
|
0
|
0
|
|
|
0
|
if (defined $Values{SignatureValue} || defined $Values{SignatureType} || defined $Values{Verify}) { |
|
|
|
0
|
|
|
|
|
208
|
0
|
|
|
|
|
0
|
$LocalValues{'EncSignatureValue'}=Hex(substr(ASN1Unwrap($ACSignature),1)); |
209
|
0
|
|
|
|
|
0
|
my $HexACSignature=Hex($ACSignatureType); |
210
|
0
|
0
|
|
|
|
0
|
if ( $HexACSignature eq "300d06092a864886f70d0101040500" ) { $LocalValues{'SignatureType'}="md5WithRSA"; } |
|
0
|
0
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
211
|
0
|
|
|
|
|
0
|
elsif ( $HexACSignature eq "300d06092a864886f70d0101050500" ) { $LocalValues{'SignatureType'}="sha1WithRSA"; } |
212
|
0
|
|
|
|
|
0
|
elsif ( $HexACSignature eq "300d06092a864886f70d0101030500" ) { $LocalValues{'SignatureType'}="md4WithRSA"; } |
213
|
0
|
|
|
|
|
0
|
elsif ( $HexACSignature eq "300d06092a864886f70d0101020500" ) { $LocalValues{'SignatureType'}="md2WithRSA"; } |
214
|
0
|
|
|
|
|
0
|
else { $LocalValues{'SignatureType'}="unrecognised"; } |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# Verify it |
218
|
0
|
0
|
|
|
|
0
|
if (defined $Values{Verify}) { |
219
|
0
|
|
|
|
|
0
|
my @ACIssuers; |
220
|
0
|
0
|
|
|
|
0
|
if ( ! defined $Values{'VOMSDIR'} ) { $Values{'VOMSDIR'}="/etc/grid-security/vomsdir"; } |
|
0
|
|
|
|
|
0
|
|
221
|
0
|
0
|
|
|
|
0
|
if ( -d $Values{'VOMSDIR'} ) { |
222
|
0
|
|
|
|
|
0
|
opendir(my $dh, $Values{'VOMSDIR'}); |
223
|
0
|
0
|
|
|
|
0
|
@ACIssuers = grep { /^[^.]/ && -f "$Values{VOMSDIR}/$_" } readdir($dh); |
|
0
|
|
|
|
|
0
|
|
224
|
0
|
|
|
|
|
0
|
closedir $dh; |
225
|
|
|
|
|
|
|
} |
226
|
0
|
|
|
|
|
0
|
$LocalValues{Verify}=0; |
227
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
0
|
for (my $II=-1;$II<@ACIssuers;$II++) { |
229
|
0
|
|
|
|
|
0
|
$Values{'IssuerDN'}=""; # set Issuer DN to be exported |
230
|
0
|
|
|
|
|
0
|
$Values{'InternalVOMSCert'}=""; # set indicator of VOMS cert attached |
231
|
0
|
|
|
|
|
0
|
my @decodedCERTS; |
232
|
0
|
0
|
|
|
|
0
|
if ( $II == -1 ) { # 1st time round try attached certs. Assuming the certlist is a chain not a list of possible issuers |
233
|
0
|
0
|
|
|
|
0
|
next if ( ! defined $LocalValues{vOMSACCertList} ); |
234
|
0
|
|
|
|
|
0
|
@decodedCERTS=@{ $LocalValues{vOMSACCertList} }; |
|
0
|
|
|
|
|
0
|
|
235
|
0
|
|
|
|
|
0
|
$LocalValues{'InternalVOMSCert'} = "Attached"; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
else { |
238
|
0
|
|
|
|
|
0
|
@decodedCERTS=readCert($Values{'VOMSDIR'}."/$ACIssuers[$II]"); |
239
|
0
|
|
|
|
|
0
|
$LocalValues{'InternalVOMSCert'} = "Local"; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
0
|
my %Chain = %{ buildchain( { trustedCAdirs => ["/etc/grid-security/certificates"], ####Can this be an option? |
|
0
|
|
|
|
|
0
|
|
243
|
|
|
|
|
|
|
suppliedcerts => \@decodedCERTS, |
244
|
|
|
|
|
|
|
trustedCAs => [] } ) }; |
245
|
|
|
|
|
|
|
|
246
|
0
|
0
|
|
|
|
0
|
next if ( @{ shift @{ $Chain{Errors} } } ); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
247
|
0
|
0
|
|
|
|
0
|
next if (! ${ $Chain{TrustedCA} }[-1] ); |
|
0
|
|
|
|
|
0
|
|
248
|
0
|
0
|
|
|
|
0
|
next if ( $Chain{'EndEntityDN'} ne $LocalValues{'IssuerDN'} ); |
249
|
0
|
|
|
|
|
0
|
my $X509REF=VOMS::Lite::X509::Examine($Chain{EndEntityCert},{Keymodulus=>"",KeypublicExponent=>""}); |
250
|
0
|
0
|
|
|
|
0
|
if (VOMS::Lite::CertKeyHelper::verifySignature( |
|
0
|
|
|
|
|
0
|
|
251
|
|
|
|
|
|
|
$LocalValues{'SignatureType'}, |
252
|
|
|
|
|
|
|
$LocalValues{'EncSignatureValue'}, |
253
|
|
|
|
|
|
|
$TBSAC, |
254
|
0
|
|
|
|
|
0
|
Hex(${ $X509REF }{'KeypublicExponent'}), |
255
|
|
|
|
|
|
|
Hex(${ $X509REF }{'Keymodulus'}))) { |
256
|
0
|
|
|
|
|
0
|
$LocalValues{'Verify'} = 1 ; last; |
|
0
|
|
|
|
|
0
|
|
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
0
|
|
|
|
|
0
|
push @Values,{}; |
262
|
0
|
|
|
|
|
0
|
foreach (keys %Values) { ${ $Values[-1] }{$_}=$LocalValues{$_}; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
0
|
|
|
|
|
0
|
return @Values; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
############################### |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub Create { |
272
|
1
|
|
|
1
|
0
|
4
|
my $inputref = shift; |
273
|
1
|
|
|
|
|
2
|
my %context = %{$inputref}; |
|
1
|
|
|
|
|
7
|
|
274
|
1
|
|
|
|
|
4
|
my @error=(); |
275
|
1
|
|
|
|
|
2
|
my @warning=(); |
276
|
1
|
|
|
|
|
2
|
my $AC; |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# Check for values which need to be defined |
279
|
1
|
50
|
|
|
|
5
|
if ( ! defined $context{'Cert'} ) { push @error, "VOMS::Lite::AC: Holder certificate not supplied"; } |
|
0
|
|
|
|
|
0
|
|
280
|
1
|
50
|
|
|
|
5
|
if ( ! defined $context{'VOMSCert'} ) { push @error, "VOMS::Lite::AC: VOMS certificate not supplied"; } |
|
0
|
|
|
|
|
0
|
|
281
|
1
|
50
|
|
|
|
5
|
if ( ! defined $context{'VOMSKey'} ) { push @error, "VOMS::Lite::AC: VOMS key not supplied"; } |
|
0
|
|
|
|
|
0
|
|
282
|
1
|
50
|
|
|
|
4
|
if ( ! defined $context{'Lifetime'} ) { push @error, "VOMS::Lite::AC: VOMS AC Lifetime not supplied"; } |
|
0
|
|
|
|
|
0
|
|
283
|
1
|
50
|
|
|
|
4
|
if ( ! defined $context{'Server'} ) { push @error, "VOMS::Lite::AC: VOMS Server FQDN not supplied"; } |
|
0
|
|
|
|
|
0
|
|
284
|
1
|
50
|
|
|
|
5
|
if ( ! defined $context{'Port'} ) { push @error, "VOMS::Lite::AC: VOMS Server Port not supplied"; } |
|
0
|
|
|
|
|
0
|
|
285
|
1
|
50
|
|
|
|
5
|
if ( ! defined $context{'Serial'} ) { push @error, "VOMS::Lite::AC: VOMS AC Serial not supplied"; } |
|
0
|
|
|
|
|
0
|
|
286
|
1
|
50
|
|
|
|
5
|
if ( ! defined $context{'Code'} ) { push @warning, "VOMS::Lite::AC: Code not supplied, using Port Value"; } |
|
0
|
|
|
|
|
0
|
|
287
|
1
|
50
|
|
|
|
3
|
if ( ! defined $context{'Attribs'} ) { push @error, "VOMS::Lite::AC: VOMS Attributes not supplied"; } |
|
0
|
|
|
|
|
0
|
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# Bail if there isn't enough information |
290
|
1
|
50
|
|
|
|
4
|
if ( @error > 0 ) { return { Errors => \@error} ; } |
|
0
|
|
|
|
|
0
|
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
# Load input data into local variables |
293
|
1
|
50
|
|
|
|
17
|
my $CertInfoRef = (($context{'Cert'} =~ /^(\060.*)$/s) ? VOMS::Lite::X509::Examine($&, {X509issuer=>"", X509serial=>"", X509subject=>""}) : undef); |
294
|
1
|
50
|
|
|
|
60
|
my $VCertInfoRef = (($context{'VOMSCert'} =~ /^(\060.+)$/s) ? VOMS::Lite::X509::Examine($&, {X509issuer=>"", subjectKeyIdentifier=>"", X509subject=>""}) : undef); |
295
|
1
|
50
|
|
|
|
25
|
my $VKeyInfoRef = (($context{'VOMSKey'} =~ /^(\060.+)$/s) ? VOMS::Lite::KEY::Examine($&, {Keymodulus=>"", KeyprivateExponent=>""}) : undef); |
296
|
1
|
50
|
|
|
|
5
|
my %CERTINFO; if ( defined $CertInfoRef ) { %CERTINFO=%$CertInfoRef; } else { push @error, "VOMS::Lite::AC: Unable to parse holder certificate."; } |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
8
|
|
|
0
|
|
|
|
|
0
|
|
297
|
1
|
50
|
|
|
|
2
|
my %VCERTINFO; if ( defined $VCertInfoRef ) { %VCERTINFO=%$VCertInfoRef; } else { push @error, "VOMS::Lite::AC: Unable to parse VOMS certificate."; } |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
7
|
|
|
0
|
|
|
|
|
0
|
|
298
|
1
|
50
|
|
|
|
2
|
my %VKEYINFO; if ( defined $VKeyInfoRef ) { %VKEYINFO=%$VKeyInfoRef; } else { push @error, "VOMS::Lite::AC: Unable to parse VOMS key."; } |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
299
|
1
|
50
|
|
|
|
5
|
if ( @error > 0 ) { return { Errors => \@error} ; } |
|
0
|
|
|
|
|
0
|
|
300
|
|
|
|
|
|
|
|
301
|
1
|
50
|
|
|
|
11
|
my $Lifetime = (($context{'Lifetime'} =~ /^([0-9]+)$/) ? $& : undef); |
302
|
1
|
50
|
|
|
|
7
|
my $Server = (($context{'Server'} =~ /^([a-z0-9_.-]+)$/) ? $& : undef); |
303
|
1
|
50
|
33
|
|
|
13
|
my $Port = (($context{'Port'} =~ /^([0-9]{1,5})$/ && $context{'Port'} < 65536) ? $& : undef); |
304
|
1
|
50
|
|
|
|
37
|
my $Serial = (($context{'Serial'} =~ /^([0-9a-f]+)$/) ? $& : undef); |
305
|
1
|
50
|
|
|
|
7
|
my $Code = (($context{'Code'} =~ /^([0-9]+)$/) ? $& : undef); |
306
|
1
|
|
|
|
|
3
|
my $AttribRef = $context{'Attribs'}; |
307
|
1
|
|
|
|
|
2
|
my $Broken = $context{'Broken'}; |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# Get the attributes from the supplied reference |
310
|
1
|
|
|
|
|
3
|
my @Attribs=(); |
311
|
1
|
|
|
|
|
4
|
foreach ( @$AttribRef ) { |
312
|
1
|
|
|
|
|
2
|
my ($cap,$rl); |
313
|
1
|
50
|
|
|
|
7
|
if ( /(\/Capability=[\w.-]+)$/ ) { $cap = $1; } |
|
1
|
|
|
|
|
5
|
|
314
|
1
|
50
|
|
|
|
70
|
if ( /(\/Role=[\w.-]+)$cap$/ ) { $rl = $1; } |
|
1
|
|
|
|
|
3
|
|
315
|
1
|
50
|
|
|
|
52
|
if ( /^((?:\/[\w.-]+)+$rl$cap)$/ ) { push @Attribs,$&; } |
|
1
|
|
|
|
|
5
|
|
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# Get any targets from the supplied reference |
319
|
1
|
|
|
|
|
3
|
my @Targets=(); |
320
|
1
|
50
|
33
|
|
|
6
|
if (defined $context{'Targets'} && $context{'Targets'} =~ /^ARRAY/ ) { |
321
|
0
|
|
|
|
|
0
|
foreach ( @{ $context{'Targets'} } ) { |
|
0
|
|
|
|
|
0
|
|
322
|
0
|
0
|
|
|
|
0
|
if (/^([a-zA-Z0-9()'*~!._;\/?:\@&=+\$,#-]|%[a-fA-F0-9]{2})+$/) { push @Targets, $1; } |
|
0
|
|
|
|
|
0
|
|
323
|
|
|
|
|
|
|
# if (/^($RE{URI})$/) { push @Targets, $1;} --- Regexp: a sledge hammer -- we shouldn't be so prescriptive |
324
|
0
|
|
|
|
|
0
|
else { push @error, "VOMS::Lite::AC: At least 1 target was an invalid URI (see eg RFC2396)";} |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# Check for errors in local variables |
329
|
1
|
50
|
|
|
|
4
|
if ( ! defined $Lifetime ) { push @error, "VOMS::Lite::AC: Invalid Lifetime"; } |
|
0
|
|
|
|
|
0
|
|
330
|
1
|
50
|
|
|
|
3
|
if ( ! defined $Server ) { push @error, "VOMS::Lite::AC: Invalid Server"; } |
|
0
|
|
|
|
|
0
|
|
331
|
1
|
50
|
|
|
|
4
|
if ( ! defined $Port ) { push @error, "VOMS::Lite::AC: Invalid Port"; } |
|
0
|
|
|
|
|
0
|
|
332
|
1
|
50
|
|
|
|
5
|
if ( ! defined $Serial ) { push @error, "VOMS::Lite::AC: Invalid Serial Number"; } |
|
0
|
|
|
|
|
0
|
|
333
|
1
|
50
|
|
|
|
5
|
if ( ! defined $Code ) { $Code = $Port; } |
|
0
|
|
|
|
|
0
|
|
334
|
1
|
50
|
|
|
|
4
|
if ( ! defined $CERTINFO{X509issuer} ) { push @error, "VOMS::Lite::AC: Unable to get holder certificate's issuer"; } |
|
0
|
|
|
|
|
0
|
|
335
|
1
|
50
|
|
|
|
4
|
if ( ! defined $CERTINFO{X509serial} ) { push @error, "VOMS::Lite::AC: Unable to get holder certificate's serial"; } |
|
0
|
|
|
|
|
0
|
|
336
|
1
|
50
|
|
|
|
4
|
if ( ! defined $CERTINFO{X509subject} ) { push @error, "VOMS::Lite::AC: Unable to get holder certificate's subject"; } |
|
0
|
|
|
|
|
0
|
|
337
|
1
|
50
|
|
|
|
3
|
if ( ! defined $VCERTINFO{X509issuer} ) { push @error, "VOMS::Lite::AC: Unable to get VOMS certificate's issuer"; } |
|
0
|
|
|
|
|
0
|
|
338
|
1
|
50
|
|
|
|
3
|
if ( ! defined $VCERTINFO{subjectKeyIdentifier} ) { push @error, "VOMS::Lite::AC: Unable to get VOMS certificate's Subject Key Identifier"; } |
|
0
|
|
|
|
|
0
|
|
339
|
1
|
50
|
|
|
|
4
|
if ( ! defined $VCERTINFO{X509subject} ) { push @error, "VOMS::Lite::AC: Unable to get VOMS certificate's subject"; } |
|
0
|
|
|
|
|
0
|
|
340
|
1
|
50
|
|
|
|
3
|
if ( ! defined $VKEYINFO{Keymodulus} ) { push @error, "VOMS::Lite::AC: Unable to get VOMS key's Modulus"; } |
|
0
|
|
|
|
|
0
|
|
341
|
1
|
50
|
|
|
|
5
|
if ( ! defined $VKEYINFO{KeyprivateExponent} ) { push @error, "VOMS::Lite::AC: Unable to get VOMS key's Exponent"; } |
|
0
|
|
|
|
|
0
|
|
342
|
1
|
50
|
|
|
|
5
|
if ( $#Attribs < 0 ) { push @error, "VOMS::Lite::AC: No Attributes supplied"; } |
|
0
|
|
|
|
|
0
|
|
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# Bail if any required variable failed to load |
345
|
1
|
50
|
|
|
|
4
|
if ( @error > 0 ) { return { Targets => \@Targets, Attribs => \@Attribs, Warnings => \@warning, Errors => \@error }; } |
|
0
|
|
|
|
|
0
|
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# Pad serial number |
348
|
1
|
|
|
|
|
9
|
$Serial =~ s/^.(..)*$/0$&/; |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# The Identity of this VOMS from first part of first Attribute |
351
|
1
|
50
|
|
|
|
6
|
my $Group=(($Attribs[0] =~ /^\/?([^\/]+)/) ? $1 : undef); |
352
|
1
|
50
|
|
|
|
4
|
if ( ! defined $Group ) { push @error, "VOMS::Lite::AC: VOMS Group not defined"; } |
|
0
|
|
|
|
|
0
|
|
353
|
1
|
50
|
|
|
|
4
|
if ( @error > 0 ) { return { Targets => \@Targets, Attribs => \@Attribs, Warnings => \@warning, Errors => \@error }; } |
|
0
|
|
|
|
|
0
|
|
354
|
1
|
|
|
|
|
4
|
my $VOMSURI=$Group."://".$Server.":".$Port; |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# Get times Now and Now + N hours |
357
|
1
|
|
|
|
|
3
|
my $NOW=time(); |
358
|
1
|
|
|
|
|
7
|
my @NOW=gmtime($NOW); |
359
|
1
|
|
|
|
|
5
|
my @FUT=gmtime($NOW+$Lifetime); |
360
|
1
|
|
|
|
|
9
|
my $NotBeforeDate = sprintf("%04i%02i%02i%02i%02i%02iZ",($NOW[5]+1900),($NOW[4]+1),$NOW[3],$NOW[2],$NOW[1],$NOW[0]); |
361
|
1
|
|
|
|
|
6
|
my $NotAfterDate = sprintf("%04i%02i%02i%02i%02i%02iZ",($FUT[5]+1900),($FUT[4]+1),$FUT[3],$FUT[2],$FUT[1],$FUT[0]); |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
########################################################### |
364
|
|
|
|
|
|
|
# OK Let's create a VOMS Attribute Certificate! This consists of: |
365
|
|
|
|
|
|
|
# AttCertVersion Holder AttCertIssuer AlgorithmIdentifier CertificateSerialNumber |
366
|
|
|
|
|
|
|
# AttCertValidityPeriod AttributeSequence UniqueIdentifier Extensions |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
# Version (=2 (i.e. 01)) |
369
|
1
|
|
|
|
|
2
|
my $AttCertVersion="020101"; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# Holder of Attribute. This this is a sequence containing the holder certificate's issuer DN and serial. |
372
|
1
|
50
|
33
|
|
|
12
|
my $HolderIssuer = Hex( ( defined $Broken && $Broken ) ? $CERTINFO{X509subject}:$CERTINFO{X509issuer} ); |
373
|
1
|
|
|
|
|
5
|
my $HolderSerial = Hex( $CERTINFO{X509serial} ); |
374
|
1
|
|
|
|
|
6
|
my $HolderInfo = ASN1Wrap( "30",ASN1Wrap( "a4",$HolderIssuer ) ).$HolderSerial; |
375
|
1
|
|
|
|
|
13
|
my $Holder = ASN1Wrap( "30",ASN1Wrap( "a0",$HolderInfo ) ); |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
# Issuer of Attribute Certificate |
378
|
1
|
|
|
|
|
4
|
my $AttCertIssuerInfo = Hex($VCERTINFO{X509subject}); |
379
|
1
|
|
|
|
|
5
|
my $AttCertIssuer = ASN1Wrap("a0",ASN1Wrap("30",ASN1Wrap("a4",$AttCertIssuerInfo))); |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# Signing Algorythm used in this Attribute Certificate |
382
|
1
|
|
|
|
|
3
|
my $AlgorithmIdentifier = "300d06092a864886f70d0101040500"; |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Serial Number |
385
|
1
|
|
|
|
|
6
|
my $SN = $Serial.DecToHex($Code); |
386
|
1
|
50
|
|
|
|
5
|
if ( length($SN) > 80 ) { |
387
|
0
|
|
|
|
|
0
|
push @warning, "AC: The size of the serial number is too large, using truncated version."; |
388
|
0
|
|
|
|
|
0
|
$SN = substr($SN,-40); |
389
|
|
|
|
|
|
|
} |
390
|
1
|
|
|
|
|
5
|
my $CertificateSerialNumber = ASN1Wrap("02",$SN); |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
# Attribute Certificate validity period |
393
|
1
|
|
|
|
|
5
|
my $AttCertValidityPeriod = ASN1Wrap("30",ASN1Wrap("18",Hex($NotBeforeDate)).ASN1Wrap("18",Hex($NotAfterDate))); |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
# Attributes from Attrib array supplied and VOMS URI (from group, server and port) |
396
|
1
|
|
|
|
|
3
|
my $VOMSOIDChunck = "060a2b06010401be45646404"; # OID, encoded-length=10, 1.3.6.1.4.1.8005.100.100.4 |
397
|
1
|
|
|
|
|
6
|
my $VOMSURIChunck = ASN1Wrap("a0",ASN1Wrap("86",Hex("$VOMSURI"))); |
398
|
1
|
|
|
|
|
4
|
my $VOMSTripleChunck = ""; |
399
|
1
|
|
|
|
|
2
|
my $VT=""; |
400
|
1
|
|
|
|
|
3
|
foreach (@Attribs) { $VT .= ASN1Wrap("04",Hex($_)); } # Concatination of wrapped Attributes |
|
1
|
|
|
|
|
10
|
|
401
|
1
|
|
|
|
|
4
|
$VOMSTripleChunck = ASN1Wrap("30",$VT); |
402
|
1
|
|
|
|
|
6
|
my $VOMSAttribChunck = ASN1Wrap("31",ASN1Wrap("30",$VOMSURIChunck.$VOMSTripleChunck)); |
403
|
1
|
|
|
|
|
6
|
my $AttributeSequence = ASN1Wrap("30",ASN1Wrap("30",$VOMSOIDChunck.$VOMSAttribChunck)); |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
#Unique Identifier |
406
|
1
|
|
|
|
|
3
|
my $UniqueIdentifier=""; # Optional and we do not specify it here |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
#Extensions |
409
|
|
|
|
|
|
|
#Targets |
410
|
1
|
|
|
|
|
3
|
my $ACTargets=""; |
411
|
1
|
|
|
|
|
1
|
my $targetInformation=""; |
412
|
1
|
|
|
|
|
4
|
foreach my $uniformResourceIdentifier (@Targets) { |
413
|
0
|
|
|
|
|
0
|
$ACTargets.=ASN1Wrap("30",ASN1Wrap("a0",ASN1Wrap("a0",ASN1Wrap("86",$uniformResourceIdentifier)))); |
414
|
|
|
|
|
|
|
} |
415
|
1
|
50
|
|
|
|
5
|
if ($ACTargets ne "") { $targetInformation=ASN1Wrap("30","0603551d37". # OID 2.5.29.55 |
|
0
|
|
|
|
|
0
|
|
416
|
|
|
|
|
|
|
"0101ff". # Critical |
417
|
|
|
|
|
|
|
ASN1Wrap("04",ASN1Wrap("30",$ACTargets)));} |
418
|
|
|
|
|
|
|
#Issuer Certs |
419
|
|
|
|
|
|
|
# my $IssuerCerts=""; |
420
|
1
|
|
|
|
|
5
|
my $IssuerCerts=ASN1Wrap("30","060a2b06010401be4564640a".ASN1Wrap("04",ASN1Wrap("30",ASN1Wrap("30",Hex($context{'VOMSCert'}))))); |
421
|
|
|
|
|
|
|
#NoRevocation |
422
|
1
|
|
|
|
|
5
|
my $NoRevAvail = "30090603551d3804020500"; # OID 2.5.29.56 + contents=Null |
423
|
|
|
|
|
|
|
#Issuer Unique ID |
424
|
1
|
|
|
|
|
7
|
my $IssuerUniqueID=ASN1Wrap("30","0603551d23".ASN1Wrap("04",ASN1Wrap("30",ASN1Wrap("80",Hex($VCERTINFO{subjectKeyIdentifier}))))); |
425
|
|
|
|
|
|
|
#Tags |
426
|
1
|
|
|
|
|
4
|
my $Tag=""; |
427
|
|
|
|
|
|
|
|
428
|
1
|
|
|
|
|
8
|
my $Extensions=ASN1Wrap("30",$targetInformation.$IssuerCerts.$NoRevAvail.$IssuerUniqueID.$Tag); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
# Concatinate and wrap into a ToBeSignedAttributeCertificate |
431
|
1
|
|
|
|
|
16
|
my $UnsignedAC = ASN1Wrap("30",$AttCertVersion. |
432
|
|
|
|
|
|
|
$Holder. |
433
|
|
|
|
|
|
|
$AttCertIssuer. |
434
|
|
|
|
|
|
|
$AlgorithmIdentifier. |
435
|
|
|
|
|
|
|
$CertificateSerialNumber. |
436
|
|
|
|
|
|
|
$AttCertValidityPeriod. |
437
|
|
|
|
|
|
|
$AttributeSequence. |
438
|
|
|
|
|
|
|
$UniqueIdentifier. |
439
|
|
|
|
|
|
|
$Extensions); |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
########################################################### |
442
|
|
|
|
|
|
|
# Make MD5 Checksum |
443
|
1
|
|
|
|
|
3
|
my $BinaryUnsignedAC = $UnsignedAC; |
444
|
1
|
|
|
|
|
6
|
$BinaryUnsignedAC =~ s/(..)/pack('C',hex($&))/ge; |
|
977
|
|
|
|
|
2210
|
|
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# Make MD5 signature and rsa sign it |
447
|
1
|
|
|
|
|
5
|
my $RSAsignedDigest = digestSign("md5WithRSA",$BinaryUnsignedAC,Hex($VKEYINFO{KeyprivateExponent}),Hex($VKEYINFO{Keymodulus})); |
448
|
|
|
|
|
|
|
|
449
|
1
|
|
|
|
|
9
|
my $ACSignature = ASN1Wrap("03",ASN1BitStr($RSAsignedDigest)); #(Always n*8 bits for MDnRSA and SHA1RSA) |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Wrap it all up |
452
|
|
|
|
|
|
|
# $AC=ASN1Wrap("30",ASN1Wrap("30",ASN1Wrap("30",$UnsignedAC.$AlgorithmIdentifier.$ACSignature))); |
453
|
1
|
|
|
|
|
9
|
$AC=ASN1Wrap("30",$UnsignedAC.$AlgorithmIdentifier.$ACSignature); |
454
|
1
|
|
|
|
|
10
|
$AC=~s/(..)/pack('C',hex($&))/ge; |
|
1063
|
|
|
|
|
2127
|
|
455
|
|
|
|
|
|
|
|
456
|
1
|
|
|
|
|
52
|
return { AC => $AC, Targets => \@Targets, Attribs => \@Attribs, Warnings => \@warning }; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
1; |
460
|
|
|
|
|
|
|
__END__ |