line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# |
2
|
|
|
|
|
|
|
# $HeadURL: https://svn.oucs.ox.ac.uk/people/oliver/pub/librpc-serialized-perl/trunk/lib/RPC/Serialized/AuthzHandler/ACL.pm $ |
3
|
|
|
|
|
|
|
# $LastChangedRevision: 1281 $ |
4
|
|
|
|
|
|
|
# $LastChangedDate: 2008-10-01 16:16:56 +0100 (Wed, 01 Oct 2008) $ |
5
|
|
|
|
|
|
|
# $LastChangedBy: oliver $ |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
package RPC::Serialized::AuthzHandler::ACL; |
8
|
|
|
|
|
|
|
{ |
9
|
|
|
|
|
|
|
$RPC::Serialized::AuthzHandler::ACL::VERSION = '1.123630'; |
10
|
|
|
|
|
|
|
} |
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
782
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
41
|
|
13
|
1
|
|
|
1
|
|
6
|
use warnings FATAL => 'all'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
47
|
|
14
|
|
|
|
|
|
|
|
15
|
1
|
|
|
1
|
|
5
|
use base 'RPC::Serialized::AuthzHandler'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
615
|
|
16
|
|
|
|
|
|
|
|
17
|
1
|
|
|
1
|
|
813
|
use Readonly; |
|
1
|
|
|
|
|
3508
|
|
|
1
|
|
|
|
|
61
|
|
18
|
1
|
|
|
1
|
|
943
|
use IO::File; |
|
1
|
|
|
|
|
1132
|
|
|
1
|
|
|
|
|
191
|
|
19
|
1
|
|
|
1
|
|
657
|
use RPC::Serialized::ACL; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
34
|
|
20
|
1
|
|
|
1
|
|
680
|
use RPC::Serialized::ACL::Group; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
32
|
|
21
|
1
|
|
|
1
|
|
5
|
use RPC::Serialized::Exceptions; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Readonly my $GROUP_RX => qr/^define\s+group\s+(\S+)\s+(.+)$/; |
24
|
|
|
|
|
|
|
Readonly my $ACL_RX => qr/^(allow|deny)\s+(\S+)\s+by\s+(\S+)\s+on\s+(\S+)$/; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub _parse_acls { |
27
|
3
|
|
|
3
|
|
4
|
my $acl_path = shift; |
28
|
|
|
|
|
|
|
|
29
|
3
|
100
|
|
|
|
40
|
my $acl_fh = IO::File->new($acl_path) |
30
|
|
|
|
|
|
|
or throw_system "Open $acl_path failed: $!"; |
31
|
|
|
|
|
|
|
|
32
|
2
|
|
|
|
|
150
|
my ( @acls, %groups ); |
33
|
2
|
|
|
|
|
46
|
while (<$acl_fh>) { |
34
|
8
|
|
|
|
|
20
|
s/#.*$//; |
35
|
8
|
|
|
|
|
17
|
s/^\s+//; |
36
|
8
|
|
|
|
|
25
|
s/\s+$//; |
37
|
8
|
100
|
|
|
|
63
|
next unless length($_); |
38
|
|
|
|
|
|
|
|
39
|
5
|
100
|
|
|
|
25
|
if ( my ( $action, $operation, $subject, $target ) = $_ =~ $ACL_RX ) { |
|
|
50
|
|
|
|
|
|
40
|
4
|
50
|
|
|
|
51
|
if ( $subject =~ s/^group:// ) { |
41
|
0
|
0
|
|
|
|
0
|
$subject = $groups{$subject} |
42
|
|
|
|
|
|
|
or throw_app |
43
|
|
|
|
|
|
|
"Reference to undefined group at '$acl_path' line $."; |
44
|
|
|
|
|
|
|
} |
45
|
4
|
50
|
|
|
|
10
|
if ( $target =~ s/^group:// ) { |
46
|
0
|
0
|
|
|
|
0
|
$target = $groups{$target} |
47
|
|
|
|
|
|
|
or throw_app |
48
|
|
|
|
|
|
|
"Reference to undefined group at '$acl_path' line $."; |
49
|
|
|
|
|
|
|
} |
50
|
4
|
|
|
|
|
21
|
push @acls, |
51
|
|
|
|
|
|
|
RPC::Serialized::ACL->new( |
52
|
|
|
|
|
|
|
operation => $operation, |
53
|
|
|
|
|
|
|
subject => $subject, |
54
|
|
|
|
|
|
|
target => $target, |
55
|
|
|
|
|
|
|
action => $action, |
56
|
|
|
|
|
|
|
); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
elsif ( my ( $name, $uri ) = $_ =~ $GROUP_RX ) { |
59
|
0
|
|
|
|
|
0
|
$groups{$name} = RPC::Serialized::ACL::Group->new($uri); |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
else { |
62
|
1
|
|
|
|
|
31
|
throw_app "Failed to parse ACLs at '$acl_path' line $."; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
1
|
|
|
|
|
19
|
return \@acls; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub new { |
70
|
4
|
|
|
4
|
0
|
7106
|
my $class = shift; |
71
|
|
|
|
|
|
|
|
72
|
4
|
100
|
|
|
|
20
|
my $acl_path = shift |
73
|
|
|
|
|
|
|
or throw_app 'ACL path not specified'; |
74
|
|
|
|
|
|
|
|
75
|
3
|
|
|
|
|
10
|
return bless { |
76
|
|
|
|
|
|
|
ACLS => _parse_acls($acl_path), |
77
|
|
|
|
|
|
|
}, $class; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub acls { |
81
|
8
|
|
|
8
|
0
|
8
|
my $self = shift; |
82
|
8
|
|
|
|
|
26
|
$self->{ACLS}; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub check_authz { |
86
|
8
|
|
|
8
|
0
|
955
|
my $self = shift; |
87
|
8
|
|
|
|
|
14
|
my ( $subject, $operation, $target ) = @_; |
88
|
|
|
|
|
|
|
|
89
|
8
|
|
|
|
|
8
|
foreach my $acl ( @{ $self->acls } ) { |
|
8
|
|
|
|
|
17
|
|
90
|
25
|
|
|
|
|
62
|
my $rc = $acl->check( $subject, $operation, $target ); |
91
|
25
|
100
|
|
|
|
103
|
next if $rc == $acl->DECLINE; |
92
|
6
|
100
|
|
|
|
60
|
return $rc == $acl->ALLOW ? 1 : 0; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
2
|
|
|
|
|
10
|
return 0; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
1; |
99
|
|
|
|
|
|
|
|