| 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__ |